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.
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;
}
}
}
For more detail: Make A Arduino Solar Radio