---

Monday, September 19, 2011

Arduino Solar Radio

I have finished my Arduino Solar Radio.


* Solar charging, via the panel on the back.
* 12 position switch to select channel number
* Seek up / seek down controls and 'store' button
* RDS display of call sign
* Frequency display
* Battery voltage display
* Solar charging current display

The software still needs a bit of attention. Its fine if the signal is good and RDS comes in quickly, but if not, then adjusting the volume or changing channel takes a few seconds to kick in. As I only really listen to Radio 4, its not a problem, but I'll get round to updating it some time.

Here are the circuit diagrams and the stripboard layout as will as a picture of the breaks in the back.






Also, here is the sketch. It uses the library I described in my previous post.


#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <Si4703_Breakout.h>
#include <Wire.h>


int resetPin = 4;
int SDIO = A4;
int SCLK = A5;
int volumePin = A2;
int rotaryPin = A3;
int upSwitchPin = 5;
int downSwitchPin = 6;
int setSwitchPin = 7;
int lcdRSPin = 3;
int lcdEPin = 2;


Si4703_Breakout radio(resetPin, SDIO, SCLK);
LiquidCrystal lcd(lcdRSPin, lcdEPin, 12, 11, 10, 9);
int channel[12];
int currentChannel = 0;
int channelNumber = 3;
int volume = 1;
long autoUpdatePeriod = 5000l;
long lastUpdate;


void setup()
{
  pinMode(upSwitchPin, INPUT);
  digitalWrite(upSwitchPin, HIGH);
  pinMode(downSwitchPin, INPUT);
  digitalWrite(downSwitchPin, HIGH);
  pinMode(setSwitchPin, INPUT);
  digitalWrite(setSwitchPin, HIGH);
  radio.powerOn();
  radio.setVolume(0);
  lcd.begin(16, 2);
  lcd.clear();
  readChannelsFromEEPROM();
  updateChannel();
  setVolume();
  displayRDS();
}


void loop()
{
  int newChannelNumber = 11 - (analogRead(rotaryPin) / 90);
  if (newChannelNumber != channelNumber)
  {
    channelNumber = newChannelNumber;
    updateChannel();
    displayRDS();
  }
  
  int up = ! digitalRead(upSwitchPin);
  int down = ! digitalRead(downSwitchPin);
  int set = ! digitalRead(setSwitchPin);
  
  if (up)
  {
    currentChannel = radio.seekUp();
    updateDisplay(); 
  }
  if (down)
  {
    currentChannel = radio.seekDown();
    updateDisplay(); 
  }
  
  if (set)
  {
    channel[channelNumber] = currentChannel;
    saveChannel(channelNumber, currentChannel);
    flashSet();
    displayRDS();
  }
  
  setVolume();
  
  if (millis() > lastUpdate + autoUpdatePeriod)
  {
    lastUpdate = millis();
    updateDisplay();
    displayRDS();
  }
  delay(50);
}


void updateChannel()
{
  clearRDS();
  currentChannel = channel[channelNumber];
  updateDisplay();
  radio.setChannel(currentChannel); 
}


void setVolume()
{
  volume = (analogRead(volumePin) + 35) / 70;
  radio.setVolume(volume);
}


void updateDisplay()
{
  lcd.setCursor(0, 0);
  if ((channelNumber + 1) < 10) lcd.print(" ");
  lcd.print(channelNumber + 1);
  
  lcd.setCursor(12, 0);
  lcd.print(currentChannel / 10); lcd.print("."); lcd.print(currentChannel % 10);
  
  lcd.setCursor(0, 1); lcd.print("Batt "); 
  int v = getBatteryVolts();  
  lcd.print(v / 10); lcd.print("."); lcd.print(v % 10); lcd.print("V");


  int i = getChargeCurrent();
  lcd.setCursor(11, 1); lcd.print("     ");  
  lcd.setCursor(11, 1);
  lcd.print(i / 10); lcd.print("mA");
    
  char rdsBuffer[10];
  getRDS(rdsBuffer);
  lcd.setCursor(3, 0);
  lcd.print(rdsBuffer);
}


void displayRDS()
{
  char rdsBuffer[10];
  getRDS(rdsBuffer);
  lcd.setCursor(3, 0);
  lcd.print(rdsBuffer);  
}


void flashSet()
{
  lcd.setCursor(3, 0);
  lcd.print("  SET   ");
  delay(500);
  clearRDS();
}


void clearRDS()
{
  lcd.setCursor(3, 0); 
  lcd.print("        ");
}


int getBatteryVolts()
{
  // volts * 10
  // potential divider 33k:10k
  // Vcc 3.3V
  // Vin 10V, Vout = 2.326V, raw at 10V = 1023 * 2.326 / 3.3 = 721
  // V*10 = raw / 72
  int raw = analogRead(1);
  return raw / 7;
}


int getChargeCurrent()
{
  // current mA * 10
  int battVoltsTen = getBatteryVolts();
  int solarVoltsTen = analogRead(0) / 7;
  int mV = (solarVoltsTen - battVoltsTen) * 100;
  int mA10 = mV / 10;
  if (mA10 < 0)
  {
    mA10 = 0;
  }
  return mA10;
}


void getRDS(char* buffer)
{
  radio.readRDS(buffer, 2000);
}


void saveChannel(int i, int channel)
{
  byte high = highByte(channel);
  byte low = lowByte(channel);
  
  EEPROM.write(i * 2, high);  
  EEPROM.write(i * 2 + 1, low);  
}


void readChannelsFromEEPROM()
{
  for (int i = 0; i < 12; i++)
  {
    byte high = EEPROM.read(i*2);
    byte low = EEPROM.read(i*2 + 1);
    int ch = high * 256 + low;
    if (ch > 700 && ch < 1500)
    {
      channel[i] = ch;
    }
  } 
}



About the Author
These are my books. Click on the image below to find out more about them.




25 comments:

thisoldgeek said...

Simon-

This is all kinds of awesome! I especially like the enclosure/case. More info, please?

Simon Monk said...

Thanks! The enclose and knobs came from Maplins (UK equivalent of Radio Shack) and the switches we standard miniature toggle.
The solar panel was reclaimed from a solar LED light kit that was on offer at DIY store for £5.

Vincenzo said...

(sorry wrong post)
Hi, Simon, please can you confirm me the schematics? If is correct can you explain the inusual lcd connection? Many thanks!
Vincenzo.

Simon Monk said...

Hi Vincenzo, yes schematic is correct. By unusual do you mean no potentiometer to connect to Vo? I only omitted it on my LCD module because I got the best contrast with it grounded anyway.

Anonymous said...

Did you tried to play some sound from the si4703 before using the amplifier? What speakers do you used(speaker impedance and watts)?

Simon Monk said...

The built-in amp on the breakout board is only 1/8 watt. I needed a bit more (1W). The speaker is 8Ω and I think 5W.

Adam said...

Hey Simon,

Your project rocks! Can you give me the dimension of the enclosure and the stripboard?

Also i would like to know how you connected the antenna into the si4703 breakout board.

Simon Monk said...

The enclosure was only just big enough, so when you have it all assembled and working un-cased, measure up and decide on your own dimensions. It will depend how big your battery is etc. The tripboard is 0.1inch hole pitch.

The antenna connection is just to the GND connection of the breakout board.

allen (in Michigan) said...

Hi Simon, any chance you might extend this project to use an AM/FM/SW radio chip?

Simon Monk said...

Hi Allen, no, for me the project is finished now. I only really listen to one channel anyway, so its already more than I need. It should be possible if you can find a breakout for one of the more feature rich relatives of the si4703.

JRMN said...

I have the Si4703 breakout board and I get a pop right before the audio plays. Do you have that problem? Also, can you tell me more about the antenna wiring?

Simon Monk said...

Yes, I get a pop too.

JRMN said...

So it's just not me. I am also experiencing something else that is kind of weird. For some reason I have to restart my arduino uno multiple times before the si4703 will start. It seems to hang during the si4703_init() function, At first I thought it might have something to do with SEN, but it can't be that because the code accounts for that. I've done some other test and it might have something to do with the fact that I have am using 0(RX) and 1(TX). Specially 1(TX). You have any idea why I would cause a conflict?

T.J said...

Hi,

Would you be able to tell me what sized speaker you used and explain how you combined the stereo signal from the radio module to create a mono signal for the speaker.

Thanks!

Simon Monk said...

TJ, The two resistors from the audio out on the radio combine the L and R into one signal.

I used a 3 inch 8 Ω speaker.

danmorg said...

Great blog of yours. I will have to go buy your book. Is there a way you can use the Ardunio from your computer to control the FM radio - tune to the station, seek, change from FM to AM. Change from Mono to Stereo. The volume. Balance. Equalizer. Etc.

And have the audio or feedback to the computer to record. I'm not sure if that is even possible. It might require plugging audio to the microphone input on the computer. But, that would be mono. I was hoping for a solution for stereo.

I would be willing to read any ideas on how this can be accomplished.

- Daniel Morgan

Federico & Nicoletta said...

hi i try to use this sketch for my arduino

but im not able to read a rds text.
can you help me?

Federico & Nicoletta said...

Hi.
i tried to use this c program for whit my arduino
but im not able to read the rds text.
can you help me?

thanks federico

iven yunis said...

Do I still have to get the arduino shield to build this or will it just attach straight it.as you can tell I am very much still a novice so envy help would be much appreciated thank u for your time.

iven yunis said...

Do I still have to get the arduino shield to build this or will it just attach straight to it.as you can tell I am very much still a novice so envy help would be much appreciated thank u for your time.

israel said...

hello simon you could give me the list of electronic components of this project would be very grateful.
thanks

israel said...

hello simon you could give me the list of electronic components of this project would be very grateful.
thanks

israel said...

hello simon you could give me the list of electronic components of this project would be very grateful.
thanks

israel said...

hello simon you could give me the list of electronic components of this project would be very grateful.
thanks

annie swati said...

Great writing post! Very helpful blog.Thanks for share this... installers