Hi everyone,
This is my first ever electronics project. I'm an IT infrastructure professional but as most of my kind, I only deal with servers, switches, routers, operating systems and so forth. I designed and breadboarded a simple fm radio with an Arduino UNO and I'm here to ask what I could improve before soldering everything together with an Arduino Nano.
Components (is it correct to call these 'active components'?):
- Aruino Uno (despite what the scheme says, planning the use a nano for the finished product)
- TEA5767 on an I2C board
- A 2x16 LCD connected through an I2C board
- XH-M177 speaker amplifier (with to 8ohm 0,5 W speakers) with a volume knob (PotMeter) which clicks off when rotated all the way left.
- Rotary encoder for tuning
Edit: new scheme after recomendations. I stated that a 100nF capacitor was enough for the LCD not to go haywire when clicking off the volume button... that was incorrect, switched it back to a 100uF (I don't have any others).
I added one capacitor because the LCD would go haywire when I switched off/on the amplifier. What do you guys think about this scheme? I am going to add a simple on/off switch to completely turn of the circuitry when not in use.
I tried catching the off switch from the amplifier but power still seems to go through after it clicked off. I found one pin that still produced around 1V (in stead of 5V) but I don't know how to use that because it's still letting current through and a digitalRead would not be able to catch the 'off' action, right?
Edit: wrong: The threshold is about 0.3*VCC (= 1.5V when VCC = 5V) so that's enough to catch it. Maybe I'll put a resistor in place to be more certain... Changed the code accordingly.
Also, I don't understand the concept around pull-down and pull-up resistors. I watched the latest TBHS (BB8 with LED art) and he speaks about it but it's all a bit too fast for me. I really do want to understand it.
The code as it is below, feel free to comment on this too (edited this too after being able to catch the volume knob off switch state):
//Libraries #include <TEA5767.h> #include <LiquidCrystal_I2C.h> #include <MD_REncoder.h> #include <EEPROM.h> //I2C address 63 (0x3F) = Radio //I2C address 96 (0x60) = LCD //Constants const int radioPin = 7; const int ampReadPin = 2; const int ampPowerPin = 3; const int REclk = 4; const int REdt = 5; const int REsw = 6; const boolean debug = false; #define I2C_ADDR 0x3F //Variables double old_freq; double temp_freq; double freq; boolean ampReadPower; boolean ampReadPower_old; int stereo; int stereo_old; int signal_level; int signal_level_old; int REdt_old; int REdt_temp; int REclk_temp; unsigned char buf[5]; unsigned long ms; boolean rotPot = true; int slowDown = 30000; //Signal chars byte level1[8] = {0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00011,0b11111}; byte level2[8] = {0b00000,0b00000,0b00000,0b00000,0b00001,0b01111,0b11111,0b11111}; byte level3[8] = {0b00000,0b00000,0b00000,0b00111,0b11111,0b11111,0b11111,0b11111}; byte level4[8] = {0b00000,0b00011,0b11111,0b11111,0b11111,0b11111,0b11111,0b11111}; byte level5[8] = {0b01111,0b11111,0b11111,0b11111,0b11111,0b11111,0b11111,0b11111}; byte loading[8] = {0b00000,0b00000,0b00000,0b11111,0b11111,0b00000,0b00000,0b00000}; //I2C pinout SLC and SDA - Arduino pins A5 and A4 LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2); TEA5767 Radio; // Rotary encoder MD_REncoder R = MD_REncoder(4, 5); void setup() { Serial.begin(57600); // Initiate rotary encoder R.begin(); // Set amplifier pins pinMode(ampReadPin, INPUT); pinMode(ampPowerPin, OUTPUT); digitalWrite(ampPowerPin, LOW); // Set Rotary Encoder pins pinMode(REclk, INPUT); pinMode(REdt, INPUT); pinMode(REsw, INPUT); // Initiate LCD lcd.begin (); lcd.backlight(); lcd.display(); lcd.clear(); // Set radio pin pinMode(radioPin, OUTPUT); digitalWrite(radioPin, HIGH); // Initiate Radio Radio.init(); EEPROM.get(0, freq); Radio.set_frequency(freq); Radio.read_status(buf); stereo = Radio.stereo(buf); signal_level = Radio.signal_level(buf); // create signal characters lcd.createChar(1, level1); lcd.createChar(2, level2); lcd.createChar(3, level3); lcd.createChar(4, level4); lcd.createChar(5, level5); lcd.createChar(6, loading); // Display loading screen and boot amp loadingScreen(2200); digitalWrite(ampPowerPin, HIGH); delay(100); ampReadPower = digitalRead(ampReadPin); if (ampReadPower == LOW) setStandby(LOW); ampReadPower_old = ampReadPower; // First display showing displayFreq(); displayStereo(); displaySignal(); } void loop() { // Read rotary encoder changes and update frequency uint8_t x = R.read(); if (x) { x == DIR_CW ? freq+=0.1 : freq-=0.1; if (freq < 87.5) freq = 87.5; if (freq > 108.0) freq = 108.0; Serial.println(freq); } // Slow down screen updates to about once every second // This is needed for the Rotary encoder to work if ((slowDown += 1) > 30000) { // Soft poweroff by reading amp power status ampReadPower = digitalRead(ampReadPin); if (ampReadPower != ampReadPower_old) { ampReadPower_old = ampReadPower; setStandby(ampReadPower); } // Get Radio status Radio.read_status(buf); // Fill radio info stereo = Radio.stereo(buf); signal_level = Radio.signal_level(buf); // Only change display if 'stereo' changes if (stereo != stereo_old) { displayStereo(); stereo_old = stereo; } // Only change display if 'signal' changes if (signal_level != signal_level_old) { displaySignal(); signal_level_old = signal_level; } // Only change display and frequency if 'freq' changes if (freq != old_freq) { displayFreq(); // Set timer for next block if (rotPot) { ms = millis(); rotPot = false; } // Only change frequency if rotary encoder hasn't been changed in 500ms if (ms + 500 < millis() and temp_freq == freq) { Radio.set_frequency(freq); old_freq = freq; rotPot = true; } temp_freq = freq; // Write frequency to EEPROM EEPROM.put(0, freq); } slowDown = 0; } } ///////////////////////// // FUNCTIONS // ///////////////////////// // Set standby state void setStandby(int state) { if (state == HIGH) { // Disable amp so we don't get noise digitalWrite(ampPowerPin, LOW); // Enable display lcd.display(); lcd.backlight(); // enable radio digitalWrite(radioPin, state); Radio.set_frequency(freq); // give radio time to load loadingScreen(1400); displayFreq(); // enable amp digitalWrite(ampPowerPin, HIGH); } else { // disable display lcd.clear(); lcd.setCursor(0,0); lcd.print("Volume off..."); delay(1000); lcd.noDisplay(); lcd.noBacklight(); // Disable radio digitalWrite(radioPin, state); } } // Display the wanted frequency void displayFreq() { lcd.setCursor(0, 0); lcd.print(" "); if (freq < 100) { lcd.print(" "); } lcd.print(freq); lcd.print(" Mhz "); } // Display wether sound is in Stereo or Mono void displayStereo() { lcd.setCursor(0, 1); if (stereo) lcd.print("Stereo"); else lcd.print("Mono "); } // Display the signal strength void displaySignal() { lcd.setCursor(11, 1); signal_level >= 2 ? lcd.write((byte) 1) : lcd.print(" "); signal_level >= 4 ? lcd.write((byte) 2) : lcd.print(" "); signal_level >= 6 ? lcd.write((byte) 3) : lcd.print(" "); signal_level >= 8 ? lcd.write((byte) 4) : lcd.print(" "); signal_level >= 10 ? lcd.write((byte) 5) : lcd.print(" "); } // Clear 'old' LCD values to force an update void clearLCDValues() { double old_freq; int stereo_old; int signal_level_old; } void loadingScreen(int loadDelay) { // Wait for sound till radio module inits completely + show loading lcd.clear(); lcd.setCursor(0,0); lcd.print(" Loading... "); lcd.setCursor(0,1); for(int x=0 ; x<16 ; x++) { //lcd.print("-"); lcd.write((byte) 6); delay((double) loadDelay/16); } lcd.clear(); }
Thank you very much for your time!
Best regards,
Thomas
Message was edited by: Thomas Hofkens changed up the scheme and code to reflect changes as proposed by others