You are on page 1of 46

Arduino-Based Shower Cabin FM Radio

FM radio built using Arduino, RDA5807M, Tiny RTC, PAM8403 class D amplifier modules, and TR028 touch panel.
IntermediateFull instructions provided17,095

Things used in this project

Hardware components

Arduino Nano R3
× 1
RDA Microelectronics RDA5807 FM radio module
× 1

NXP NOKIA 5110 LCD 3V-5V version


× 1

Tiny RTC module (DS1307 + 24c32 EEPROM)


× 1

PAM8403 - 2X3W class D amplifier


× 1

Texas Instruments LM2596 DC-DC Step Down Converter


Module × 1

LIR2032 3.6V Rechargeable Battery


× 1

Resistor 100 ohm


× 1

Resistor 1k ohm
× 1

Resistor 10k ohm


× 6

Resistor 100k ohm


× 1

Infineon IRLZ44 power Mosfet


× 1

PEIYING PY1010C 60W 4Ohm speakers.


× 1

12V 3A power supply found in scrap.


× 1

2200 uF 25V capacitors


× 2

Capacitor 100 µF
× 1

3W LED bulbs to replace existing G4 10W halogens


× 1

Story
A few years ago, I bought a Chinese shower cabin which has installed the TR028 control system with radio. Unfortunately one nice day I found this
system competely dead. Nobody could repair it so I bought another, cheaper shower radio. It died after about one year.

My family used to have a radio in the shower cabin, so I started studiyng how these radios were made. Inside the TR028 system I found a strange
TEA5767 module. Some searches let me know that it is a small cheap FM radio module. In search results I found another interesting FM radio module
- RDA5807. It's very similar to TEA5767, but has RDS, volume control and bass boost features. So my decision was to use RDA5807 in my new
project.

I searched the Internet and found several projects where RDA5807 module was used:

 Main project which inspired my vision.


 Variation where I found a great signal strengh sign and more useful information.

 Another variation.

 Great radio module library

 Useful information (in russian).

 One More

It was possible to repeat one of these projects, but no one met my vision exactly.

My vision was:
 The device with touch screen to ensure water proof construction. (I used enclosure with touch panel from dead TR0289).

 Radio

 Several favorite radio stations presets

 Volume control

 Automatic radio station seek feature

 Possibility to memorize seeked radio station

 A clock to see the current time.

 On/Off feature

 Light control

 Some minor information display like temperature inside a cabin, RDS.

On Aliexpress I bought RDA5807, Tiny RTC with 32kb EEPROM, PAM8403, NOKIA 5110 LCD, LM2596 modules for less than 10€ and started
experiments.

What finaly I got:


 FM radio with 2 rows (!) RDS

 6 presets for favorite radio stations

 Automatic or manual tuning

 Possibility to store favorite radio station to one of 6 presets

 Volume and bass boost control

 Shower cabin lights control

 A clock ant calendar


 RSSI (radio signal strengh indicator)

 Stereo mode indicator

 On/Off feature

Some pictures of the project

Testing on breadboard:

For NOKIA 5110 display I found a nice library


Almost happy with information display

Understood how the TR028 touch panel works. Actualy it's 2 columns X 7 rows keypad. To operate it I used this library.
TR028 touch panel
Aded cabin lights control. Nothing special, just mosfet.

When everything is working on breadboard, it's time to move modules to another board.

Assembled board placed in the box. You can notice that I've desoldered the USB socket and soldered the cable directly. It's for possibility to connect a
PC and future software improvements.
Desoldered USB socket
Some experiments with panel look.
Final tests on the table.
Final view. Installed in the shower cabin.

How it works:
 The radio won't turn-on after power supply is connected. This prevents of radio playing if powerline is not stable or power was lost. To turn-
on the radio first time you have to connect power supply and after few seconds press the power key. The radio will play last played radio station with
volume at level 03. Operating mode will be VOLUME control. To turn-off the radio simly press the power key. The device will turn off LCD, LCD
backlite, amplifier and LED / halogen lamp.

 To seek a radio station you can chose Auto or Manual tuning mode by pressing the "Mod" button. By pressing "<" or ">" buttons, the radio
will search a radio station decresing or increasing frequency. To store a found radio station press the "Mem" button and you'll have 4 seconds to
select one of six presets you like to store to.

 To see current date press the I (info) key. The date will be displayed 4 seconds. This part of code can be optimized because it uses a
delay() function.

 To adjust the clock press and hold the D key for at least 2 sec when you hear a hour ending signals (time signals), or see last seconds of a
hour on some accurate clock. Release the D key to set hh.00.00. If your clock was late from 15 to 1 minutes, minutes and seconds will be set to 00
and hours will be increased by 1 and if your clock was hurry from 1 to 15 minutes, only minutes and seconds will be set to 00 after adjustment
procedure.
What would I change:
 The resonator on RTC module to have better accuracy but clock adjustment feature lets to solve this problem.

 The 5110 LCD to a bigger and brighter one. May be some 1, 8" or 2.0" color LCD because sometimes it's hard to read information on
NOKIA 5110 LCD used in the project.

 The PAM8403 amplifier to PAM8610 which has 2x15W output power or TDA7297 with same characteristics.

Conclusion:
I'm happy how my new project works. No problems were observed after 1 month of working except the clock accuracy.

I'm not a programmer so the code can be optimized better. My C/C++ programming experience is about one year, self learned. It's my first useful
project using Arduino platform and the first project which I'm sharing on the hub. Please understand and forgive me for possible mistakes and my bad
English.

If you have any questions do not hesistate to ask in comments or PM.

Update 1.: Minor hardware and software updates.

Hardware - installed a 2A fuse on 12V line. Just for safety reason.

Software - added the line 586 menu = 1; This restores mode to VOLUME after pressing the power key.

Update 2:

Unfortunately the LCD in my radio is going to die.


Dying LCD

So I'm in search for cheap NOKIA 5110 LCD alternative. I won't install a new 5110 LCD because it's small and hard to read. I think I'll experiment with
1.8" TFT LCD. The good things - it's bigger, brighter, has better resolution. The bad things - I'm sure the 1.8" TFT will eat more resources which are
critical.

Your advices regarding LCD replacemen are welcome.

Schematics
Project schematic (Drawn using Qick Coper app)
Code
 Project sketch

 Signal strenght symbols

Project sketch
Arduino
/////////////////////////////////////////////////////////////////
// Arduino based shower FM Radio Project //
// Arduino NANO, RDA5807M, RTC, EEPROM, LCD5110, Thermistor //
/////////////////////////////////////////////////////////////////

#include <LCD5110_Graph.h> //http://www.rinkydinkelectronics.com/library.php?id=48


#include <AT24CX.h> //https://github.com/cyberp/AT24Cx
#include <Wire.h> //Arduino IDE included
#include <RDSParser.h> //http://www.mathertel.de/Arduino/RadioLibrary.aspx
#include <radio.h> //http://www.mathertel.de/Arduino/RadioLibrary.aspx
#include <RTClib.h> //https://github.com/adafruit/RTClib
#include <RDA5807M.h> //http://www.mathertel.de/Arduino/RadioLibrary.aspx
#include <Keypad.h> //http://playground.arduino.cc/Code/Keypad
#define MAXmenu 4
#define ledPin 13
#define blPin 7

//define the cymbols on the buttons of the keypads


char keys[7][2] = {
{'L', 'P'}, //LED, POWER
{'I', 'D'}, //INFO, DISPLAY
{'1', '2'}, //presets
{'3', '4'}, //from 1
{'5', '6'}, //to 6
{'M', 'm'}, //MODE, MEM
{'<', '>'} //down, up
};
byte rowPins[7] = {11, 12, 10, 17, 9, 16, 8}; //connect to the row pinouts of the keypad
byte colPins[2] = {15, 14}; //connect to the column pinouts of the keypad

//Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, 7, 2 );

boolean bass = 0, dspl = 0, memdisplay = 0, mempress = 0, adj = 0;


boolean ledPin_state, power_state;
int menu;
int volume, volumeOld = 5;
int frequency, frequencyOld;
int txtl = 0, temparray = 0;
int samples[5];
unsigned int status[6];
unsigned long timeprevious = 0, timeprev = 0;

// EEPROM object
AT24CX mem;

RTC_DS1307 rtc;

//(clk, din, dc, ce, rst)


LCD5110 lcd(6, 5, 4, 2, 3);

// Create an instance of a RDA5807 chip radio


RDA5807M radio;

/// get a RDS parser


RDSParser rds;

extern unsigned char SmallFont[];


extern uint8_t signal5[];
extern uint8_t signal4[];
extern uint8_t signal3[];
extern uint8_t signal2[];
extern uint8_t signal1[];

//--------------------------SETUP----------------------------------//
void setup()
{
analogReference(EXTERNAL);
Serial.begin(9600);
Wire.begin();

// Initialize the Radio


radio.init();
radio.debugEnable();

//initialize the Screen


lcd.InitLCD();
lcd.clrScr();
//lcd.setContrast(45); //adjust if default isn't good
lcd.setFont(SmallFont);
lcd.enableSleep(); //stand-by mode

power_state = 0; //don't "power-on" of the unit (stand by mode) when power supply is connected

//inicialize the keyboard


keypad.addStatedEventListener(keypadEvent); // Add an event listener for this keypad
keypad.setHoldTime(1500);

pinMode(ledPin, OUTPUT); // Sets the digital pin as output.


pinMode(blPin, OUTPUT); // Sets the digital pin as output.
digitalWrite(ledPin, LOW); // Turn the LED off.
digitalWrite(blPin, LOW); // Turn the BL off (stand-by mode)
ledPin_state = digitalRead(ledPin); // Store initial LED state. HIGH when LED is on.

//uncomment if rtc need to be adjusted


/*if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2018, 3, 13, 22, 33, 0));
}*/

// read value of last frequency


frequency = mem.readInt(201);

volume = 2; //volume level at start


menu = 1; //shows VOLUMME mode at start

if (volume < 0) volume = 0;


if (volume > 15) volume = 15;
if (frequency < 0) frequency = 0;
if (frequency > 210) frequency = 210;

WriteReg(0x02, 0xC00d); // write 0xC00d into Reg.2 ( soft reset, enable,RDS, ) //bbz
canal(frequency);

// setup the information chain for RDS data.


radio.attachReceiveRDS(RDS_process);
rds.attachServicenNameCallback(DisplayServiceName);
//rds.attachTimeCallback(DisplayTime); //for future use. very inaccurate when RDS signal is weak.
rds.attachTextCallback(DisplayText);
}

//-----------------------end of Setup------------------------------------//

//--------------------------LOOP----------------------------------------//

void loop()
{
if ( frequency != frequencyOld)
{
frequencyOld = frequency;
mem.writeInt(201, frequency);
canal(frequency);
}

if (volume != volumeOld)
{
volumeOld = volume;
WriteReg(5, 0x84D0 | volume);
}

//read the keyboard


char key = keypad.getKey();

//check for RDS data


radio.checkRDS();

// reads temperature probe every 0,6 sec 5 times and calculates average
float average;
unsigned long timenow = millis();
if ((unsigned long)(timenow - timeprevious) > 600) {
timeprevious = timenow;
samples[temparray] = analogRead(A7);
temparray++;
}
if (temparray == 5) {
// calculating average of readings
average = 0;
for (int i = 0; i < 5; i++) {
average += samples[i];
}
printTemp(average);
temparray = 0;
}

// 4 sec timeout for MEM display and enter


unsigned long dabar = millis();
if (mempress == 1) {
timeprev = dabar;
memdisplay = 1;
mempress = 0;
}
if (memdisplay == 1) {
if ((unsigned long)(dabar - timeprev) < 4000) {
memdisplay = 1;
}
else {
memdisplay = 0;
}
}

/*Time adjustment instructions:


1. Run serial monitor
2. Set 9600 boud
3. Hit enter to activate serial reading
4. Write hXX, where XX is current hour reading on some time server and hit enter to adjust RTC hours. Serial monitor should write "Hours XX"
5. Write mXX, where XX is current minutes reading on some time server and hit enter to adjust RTC minutes. Serial monitor should write "Minutes XX"
6. Write sXX, where XX is current seconds reading on some time server and hit enter to adjust RTC seconds. Serial monitor should write "Seconds XX"
7. You can adjust only hours. I.e. when day light saving time was changed.
8. You can adjust only seconds if you need to correct time only.
9. If RTC has to be adjusted from zero (year, month, day, etc), uncomment RTC adjustment statement lines and upload the sketch.
*/
DateTime now = rtc.now();
if (Serial.available() > 0) {
char t = Serial.read();
switch (t) {
case ('h'): {
unsigned int hours = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hours, now.minute(), now.second()));
Serial.println(F("Hours"));
Serial.println(hours);
break;
}
case ('m'): {
unsigned int mins = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), mins, now.second()));
Serial.println(F("Minutes"));
Serial.println(mins);
break;
}
case ('s'): {
unsigned int sec = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), sec));
Serial.println(F("Seconds"));
Serial.println(sec);
break;
}
}
}

//display various information on LCD


printSignalStrength();
printLines();

printTime();
printFreq();
printStereo();
printMode();
printMenu();
printDate();
lcd.update();
}
//------------------------End of Loop------------------------------------//

void printSignalStrength() //from 0000 to 1111 (0-63)


{
unsigned int sig;
Readstatus();
sig = status[1] / 1000;
if ((sig >= 0) && (sig <= 12)) {
lcd.drawBitmap(1, 1, signal1, 17 , 6);
}
if ((sig >= 13) && (sig <= 24)) {
lcd.drawBitmap(1, 1, signal2, 17 , 6);
}
if ((sig >= 25) && (sig <= 36)) {
lcd.drawBitmap(1, 1, signal3, 17 , 6);
}
if ((sig >= 37) && (sig <= 48)) {
lcd.drawBitmap(1, 1, signal4, 17 , 6);
}
if (sig >= 49) {
lcd.drawBitmap(1, 1, signal5, 17 , 6);
}
}

void printLines()
{
lcd.drawLine(0, 9, 84, 9);
lcd.drawLine(0, 39, 84, 39);
}

void printTemp(float average) //could be optimised :)


{
average /= 5;
average = 1023 / average - 1;
average = 51700 / average;

float steinhart;
steinhart = average / 50000; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= 3950; // 1/B * ln(R/Ro)
steinhart += 1.0 / (25 + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // invert
steinhart -= 273.15; // celsius conversion

int tmp = round(steinhart);


lcd.printNumI(tmp, 60, 1, 2);
lcd.print(F("~C"), 72, 1);
}

/// Update the ServiceName text on the LCD display when in RDS mode.
void DisplayServiceName(char *name)
{
lcd.print(name, 18, 22);
}

void DisplayText(char *text)


{
//scroll second RDS line
lcd.print(text, txtl, 30);
txtl = txtl - 66;
if (txtl == -396) txtl = 0;
}

void printTime()
{
DateTime now = rtc.now();
lcd.printNumI(now.hour(), 24, 1, 2, '0');
lcd.print(":", 36, 1);
lcd.printNumI(now.minute(), 42, 1, 2, '0');
}

void printDate()
{
if (dspl == 1) { //checks if display key was pressed
ClearRDS();
DateTime now = rtc.now();
lcd.printNumI(now.year(), 12, 22, 4);
lcd.print(".", 36, 22);
lcd.printNumI(now.month(), 42, 22, 2, '0');
lcd.print(".", 54, 22);
lcd.printNumI(now.day(), 60, 22, 2, '0');

int dw = now.dayOfTheWeek();
switch (dw) {
case 0:
lcd.print(F("Sekmadienis"), CENTER, 30); //sunday F() macro to save sdram
break;
case 1:
lcd.print(F("Pirmadienis"), CENTER, 30); //monday etc...
break;
case 2:
lcd.print(F("Antradienis"), CENTER, 30);
break;
case 3:
lcd.print(F("Treciadienis"), CENTER, 30);
break;
case 4:
lcd.print(F("Ketvirtadienis"), CENTER, 30);
break;
case 5:
lcd.print(F("Penktadienis"), CENTER, 30);
break;
case 6:
lcd.print(F("Sestadienis"), CENTER, 30);
break;
}
lcd.update();
delay(4000); //not optimal
ClearRDS();
dspl = 0;
}
}

void printMode()
{
lcd.print(F("MODE "), 0, 41);
}

void printMenu()
{
if (menu == 1) {
lcd.print(F("VOLUME "), 30, 41);
if (volume < 0) {
lcd.print(F("XX"), 72, 41);
}
else
lcd.printNumI(volume + 1, 72, 41, 2, '0');
}
if (menu == 2) {
lcd.print(F("AUTO-TUNE"), 30, 41);
}
if (menu == 3) {
lcd.print(F("MAN.-TUNE"), 30, 41);
}
if (menu == 4) {
lcd.print(F(" BASS "), 30, 41);
if (bass == 0) {
lcd.print(F("OFF"), 66, 41);
}
else
lcd.print(F(" ON"), 66, 41);

}
}

void printFreq() //displays current frequency


{
int frHundr, frDec;
unsigned int fr;
fr = 870 + frequency;
frHundr = fr / 10;
frDec = fr % 10;
lcd.printNumI(frHundr, 30, 12, 3);
lcd.print(F("."), 48, 12);
lcd.printNumI(frDec, 54, 12, 1);
lcd.print(F("MHz"), 66, 12);
}

void printStereo()
{
if (memdisplay == 1) { //if MEM key was pressed
lcd.print(F("MEM>"), 0, 12);
}
//Stereo detection
else if ((status[0] & 0x0400) == 0)
lcd.print(F("( )"), 0, 12); //means MONO
else
lcd.print (F("(ST)"), 0, 12); //means STEREO
}

void search(byte direc) //automatic seek


{
byte i; //seek up or down
if (!direc) WriteReg(0x02, 0xC30d);
else WriteReg(0x02, 0xC10d);

for (i = 0; i < 10; i++) {


delay(200);
Readstatus();
if (status[0] & 0x4000)
{
frequency = status[0] & 0x03ff;
break;
}
}
}

void canal( int canal) //direct frequency


{
byte numberH, numberL;
numberH = canal >> 2;
numberL = ((canal & 3) << 6 | 0x10);
Wire.beginTransmission(0x11);
Wire.write(0x03);
Wire.write(numberH); // write frequency into bits 15:6, set tune bit
Wire.write(numberL);
Wire.endTransmission();
}

//RDA5807_adrs=0x10;
// I2C-Address RDA Chip for sequential Access
int Readstatus()
{
Wire.requestFrom(0x10, 12);
for (int i = 0; i < 6; i++) {
status[i] = 256 * Wire.read () + Wire.read();
}
Wire.endTransmission();

}
//RDA5807_adrr=0x11;
// I2C-Address RDA Chip for random Access
void WriteReg(byte reg, unsigned int valor)
{
Wire.beginTransmission(0x11);
Wire.write(reg); Wire.write(valor >> 8); Wire.write(valor & 0xFF);
Wire.endTransmission();
//delay(50);
}

void RDS_process(uint16_t block1, uint16_t block2, uint16_t block3, uint16_t block4) {


rds.processData(block1, block2, block3, block4);
}
void ClearRDS()
{
lcd.print(" ", 0, 22);
lcd.print(" ", 0, 30);
}

// Taking care of some special events.


void keypadEvent(KeypadEvent key, KeyState kpadState ) {
switch (kpadState) {
/*
Another way to adjust time:
1. Press and hold key D for at least 2 sec, when you hear hour ending time signals, or see last hour seconds
on some accurate clock.
2. Release key D to adjust hh.00.00.
3. Ahter adjustment, if your clock was late from 15 to 1 minutes, minutes and seconds will be 00
and hours will be increased by 1.
4. If your clock was hurry from 1 to 15 minutes, only minutes and seconds will be 00.
*/
case HOLD:
if (key == 'D' && power_state == 1) {
adj = 1;
}
break;
case RELEASED:
if (key == 'D' && adj == 1) {
DateTime now = rtc.now();
if (now.minute() >= 45 && now.minute() <= 59) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, 0, 0));
}
if (now.minute() >= 1 && now.minute() <= 15) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 0, 0));
}
adj = 0;
}
break;
case PRESSED:
if (key == 'M' && power_state == 1) {
memdisplay = 0;
menu++;
if (menu > MAXmenu)menu = 1;
}

if (key == '>' && power_state == 1) {


memdisplay = 0;
switch (menu)
{
case 1:
if (volume < 0) {
if (bass == 0) {
WriteReg(0x02, 0xD00D);
volume = 0;
}
if (bass == 1) {
WriteReg(0x02, 0xC00D);
volume = 0;
}
}
else
volume++;

if (volume > 15)volume = 15;


break;
case 2:
search(0);
ClearRDS();
break;
case 3:
frequency++;
if (frequency > 210)frequency = 210; // upper frequency limit
ClearRDS();
break;
case 4:
if (bass == 0) {
bass = 1;
WriteReg(0x02, 0xD00D);
}
break;
}
}

if (key == '<' && power_state == 1) {


memdisplay = 0;
switch (menu)
{
case 1:
volume--;
if (volume < 0) {
WriteReg(0x02, 0x800D);
//volume = 0;
}
break;
case 2:
search(1);
ClearRDS();
break;
case 3:
frequency--;
if (frequency < 0)frequency = 0;
ClearRDS();
break;
case 4:
if (bass == 1) {
bass = 0;
WriteReg(0x02, 0xC00D);
}
break;
}
}
// LED lights on/off
if (key == 'L' && power_state == 1) {
digitalWrite(ledPin, !digitalRead(ledPin));
ledPin_state = digitalRead(ledPin); // Remember LED state, lit or unlit.
}
// turns "power" on or off (stand-by mode)
if (key == 'P')
{
digitalWrite(blPin, !digitalRead(blPin));
power_state = digitalRead(blPin);
if (power_state == 0) {
lcd.enableSleep();
digitalWrite(ledPin, LOW);
}
else lcd.disableSleep();
volume = 2;
menu = 1;
}

if (key == '1' && power_state == 1) {


switch (memdisplay) {
case 0:
frequency = mem.readInt(110);
ClearRDS();
break;
case 1:
mem.writeInt(110, frequency);
memdisplay = 0;
break;

}
}
if (key == '2' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(120);
ClearRDS();
break;
case 1:
mem.writeInt(120, frequency);
memdisplay = 0;
break;

}
}
if (key == '3' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(130);
ClearRDS();
break;
case 1:
mem.writeInt(130, frequency);
memdisplay = 0;
break;

}
}
if (key == '4' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(140);
ClearRDS();
break;
case 1:
mem.writeInt(140, frequency);
memdisplay = 0;
break;

}
}
if (key == '5' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(150);
ClearRDS();
break;
case 1:
mem.writeInt(150, frequency);
memdisplay = 0;
break;
}
}

if (key == '6' && power_state == 1) {


switch (memdisplay) {
case 0:
frequency = mem.readInt(160);
ClearRDS();
break;
case 1:
mem.writeInt(160, frequency);
memdisplay = 0;
break;
}
}

if (key == 'm' && power_state == 1) {


mempress = 1;
}
else {
mempress = 0;
}

if (key == 'I' && power_state == 1) {


dspl = 1;
}
break;
}
}

Credits

Saulius Bandzevičius
1 project • 88 followers
FollowContact

Comments
Write Preview

Post

Luigi Provenza
5 years ago
Great project! Looks like very nice.

 Thank

 Reply

Saulius Bandzevičius
5 years ago
Thank you!

 Thank

 Reply to conversation

OS BULUT
4 years ago
I get the following error when compiling.
Class keypad has no memmernamedaddstaced Eventlistener
How do I fix it?

 Thank

 Reply

 1 thank

Saulius Bandzevičius
4 years ago
Os Bulut
I'm sorry for late answer. I don't getting all notifications about comments.
Did you solved the problem?

 Thank

 Reply to conversation

 1 thank

dsandu
3 years ago
Mr. SAULIUS,
I am working on conducting this "FM Radio" experiment, I designed a printed circuit but I had some software problems that were solved.
Who consumes the resources of memory ???
Can anything be done?
Thanks!

 Thank

 Reply

 1 thank

Saulius Bandzevičius
3 years ago
Dear dsandu,
I think bigest memory consumers are LCD library, writings on LCD, writings on serial port. Because of limited memory I didn't implemented the clock adjustment.
Did you finished this project?
 Thank

 Reply to conversation

randyrue
a year ago
This looks great! Can you tell me how you figured out to get and display the RDS information? I'm looking for examples online for the RDA5807M and using the
radio.h library and your code is the most complete one I've found. I've copied your RDS_process, DisplayServiceName and DisplayText functions. I included the
three "attach" calls in my setup, and a call to checkRDS in the loop. But I never get any text in the ServiceName or Text. Am I right in guessing that checkRDS
should pull any existing information or do I need to be doing anything else? Also, I see you writing directly to the radio chip with:
WriteReg(0x02, 0xC00d); // write 0xC00d into Reg.2 ( soft reset, enable,RDS, ) //bbz
Is that necessary somehow?
Hope to hear from you, I'd be grateful for any help.

ФМ радио за туш кабину заснован на Ардуину


ФМ радио направљен коришћењем Ардуино, РДА5807М, Тини РТЦ, ПАМ8403 модула појачала класе Д и ТР028 панела осетљивог на додир.
СредњиДостављена су пуна упутства17,095
Ствари које се користе у овом пројекту

Хардверске компоненте

Ардуино Нано Р3
× 1

РДА Мицроелецтроницс РДА5807 ФМ радио модул


× 1

НКСП НОКИА 5110 ЛЦД 3В-5В верзија


× 1
Мали РТЦ модул (ДС1307 + 24ц32 ЕЕПРОМ)
× 1

ПАМ8403 - 2Кс3В појачало класе Д


× 1

Текас Инструментс ЛМ2596 ДЦ-ДЦ Степ Довн


Цонвертер Модуле × 1

ЛИР2032 3.6В пуњива батерија


× 1

Отпорник 100 ома


× 1

Отпорник 1к ома
× 1

Отпорник 10к ома


× 6

Отпорник 100 к ома


× 1

Инфинеон ИРЛЗ44 повер Мосфет


× 1

ПЕИИИНГ ПИ1010Ц 60В 4Охм звучници.


× 1

12В 3А напајање пронађено у отпаду.


× 1

2200 уФ 25В кондензатори


× 2

Кондензатор 100 µФ
× 1

3В ЛЕД сијалице за замену постојећих Г4 10В


халогена × 1

Прича
Пре неколико година купио сам кинеску туш кабину у којој је уграђен контролни систем ТР028 са радиом. Нажалост, једног лепог дана нашао
сам овај систем потпуно мртав. Нико није могао да га поправи па сам купио други, јефтинији радио за туш . Умро је након отприлике годину
дана.

Моја породица је имала радио у туш кабини, па сам почео да проучавам како су ови радио апарати направљени. Унутар система ТР028
нашао сам чудан ТЕА5767 модул. Неке претраге су ми дале до знања да је то мали јефтин ФМ радио модул. У резултатима претраге нашао
сам још један занимљив ФМ радио модул - РДА5807. Веома је сличан ТЕА5767, али има РДС, контролу јачине звука и функције за
појачавање баса. Тако да је моја одлука била да користим РДА5807 у свом новом пројекту.

Претражио сам Интернет и нашао неколико пројеката у којима је коришћен модул РДА5807:

 Главни пројекат који је инспирисао моју визију.

 Варијација у којој сам пронашао одличан знак за јачину сигнала и више корисних информација.
 Друга варијација.

 Одлична библиотека радио модула

 Корисне информације (на руском).

 Још једно

Било је могуће поновити један од ових пројеката, али нико није тачно испунио моју визију.

Моја визија је била:


 Уређај са екраном осетљивим на додир који обезбеђује водоотпорну конструкцију. (Користио сам кућиште са тоуцх панелом од
мртвог ТР0289).

 Радио

 Неколико унапред подешених омиљених радио станица

 Контрола јачине звука

 Функција аутоматског тражења радио станице

 Могућност меморисања тражене радио станице

 Сат за приказ тренутног времена.

 Он/Офф функција

 Контрола светла

 Неки мањи приказ информација као што је температура у кабини, РДС.

На Алиекпрессу сам купио РДА5807, Тини РТЦ са 32кб ЕЕПРОМ-а, ПАМ8403, НОКИА 5110 ЛЦД, ЛМ2596 модуле за мање од 10€ и почео
експерименте.

Шта сам коначно добио:


 ФМ радио са 2 реда (!) РДС

 6 меморисаних подешавања за омиљене радио станице

 Аутоматско или ручно подешавање

 Могућност чувања омиљене радио станице у једној од 6 меморисаних поставки

 Контрола јачине и појачања баса

 Контрола осветљења туш кабине

 Календар са сатом и мравама

 РССИ (индикатор јачине радио сигнала)


 Индикатор стерео режима

 Он/Офф функција

Неколико слика пројекта

Тестирање на матичној плочи:

За екран НОКИА 5110 нашао сам лепу библиотеку


Скоро задовољан приказом информација

Разумео како функционише ТР028 тоуцх панел. У ствари, то је тастатура од 2 колоне Кс 7 редова. За рад користио сам ову библиотеку .
ТР028 тоуцх панел
Додата контрола светла у кабини. Ништа посебно, само мосфет.

Када све ради на матичној плочи, време је да преместите модуле на другу плочу.

Састављена плоча постављена у кутију. Можете приметити да сам одлемио УСБ утичницу и директно залемио кабл. Служи за могућност
повезивања рачунара и будућа побољшања софтвера.
Одлемљена УСБ утичница
Неки експерименти са изгледом панела.
Завршни тестови на столу.
Финални поглед. Инсталиран у туш кабини.

Како то ради:
 Радио се неће укључити након што је напајање прикључено. Ово спречава пуштање радија ако струјна линија није стабилна или је
дошло до губитка струје. Да бисте први пут укључили радио, морате прикључити напајање и након неколико секунди притиснути тастер за
укључивање. Радио ће пуштати последњу радио станицу са јачином звука на нивоу 03. Режим рада ће бити контрола ВОЛУМЕ. Да бисте
искључили радио, једноставно притисните тастер за укључивање. Уређај ће искључити ЛЦД, ЛЦД позадинско осветљење, појачало и
ЛЕД/халогену лампу.

 Да бисте тражили радио станицу, можете одабрати режим аутоматског или ручног подешавања притиском на дугме
"Мод". Притиском на дугме "<" или ">", радио ће претраживати радио станицу која смањује или повећава фреквенцију. Да бисте сачували
пронађену радио станицу, притисните дугме "Мем" и имаћете 4 секунде да изаберете једну од шест меморисаних подешавања на које
желите да сачувате.

 Да видите тренутни датум притисните тастер И (инфо). Датум ће бити приказан 4 секунде. Овај део кода се може оптимизовати јер
користи функцију делаи().

 Да бисте подесили сат, притисните и држите тастер Д најмање 2 секунде када чујете сигнале о завршетку сата (временски
сигнали) или видите последње секунде сата на неком тачном сату. Отпустите тастер Д да бисте подесили хх.00.00. Ако је ваш сат каснио са
15 на 1 минут, минуте и секунде ће бити подешене на 00 и сати ће бити увећани за 1, а ако је ваш сат журио са 1 на 15 минута, само минуте
и секунде ће бити подешене на 00 након процедуре подешавања .

Шта бих променио:


 Резонатор на РТЦ модулу има бољу тачност, али функција подешавања сата омогућава да се реши овај проблем.

 5110 ЛЦД на већи и светлији. Може бити неки ЛЦД у боји од 1, 8" или 2,0" јер је понекад тешко прочитати информације о НОКИА
5110 ЛЦД коришћеном у пројекту.

 ПАМ8403 појачало за ПАМ8610 који има излазну снагу 2к15В или ТДА7297 са истим карактеристикама.

Закључак:
Срећан сам како мој нови пројекат функционише. Након 1 месеца рада нису примећени проблеми осим тачности сата.

Нисам програмер па се код може боље оптимизовати. Моје Ц/Ц++ искуство програмирања је око годину дана, сам научио. То је мој први
користан пројекат који користи Ардуино платформу и први пројекат који делим на чворишту. Молим вас да разумете и опростите ми за могуће
грешке и мој лош енглески.

Ако имате било каквих питања, не оклевајте да их питате у коментарима или ПМ.

Ажурирање 1.: Мања ажурирања хардвера и софтвера.

Хардвер - инсталиран осигурач од 2А на 12В линији. Само из безбедносних разлога.

Софтвер - додао је ред 586. Ово враћа режим на ВОЛУМЕ након притиска на тастер за укључивање. menu = 1;

Ажурирање 2:

Нажалост, ЛЦД у мом радију ће се угасити.


Умирући ЛЦД

Зато сам у потрази за јефтином алтернативом за НОКИА 5110 ЛЦД. Нећу инсталирати нови 5110 ЛЦД јер је мали и тежак за читање. Мислим
да ћу експериментисати са 1,8" ТФТ ЛЦД-ом. Добре ствари - већи је, светлији, има бољу резолуцију. Лоше ствари - сигуран сам да ће ТФТ од
1,8" појести више ресурса који су критични.

Ваши савети у вези са заменом ЛЦД-а су добродошли.

Шеме
Шема пројекта (нацртана помоћу апликације Кицк Цопер)
Код
 Скица пројекта

 Симболи јачине сигнала

Скица пројекта
Ардуино
///////////////////////////////////////////////// ////////////////
// ФМ радио пројекат туша заснован на Ардуину //
// Ардуино НАНО, РДА5807М, РТЦ, ЕЕПРОМ, ЛЦД5110, термистор //
///////////////////////////////////////////////// ////////////////

#инцлуде <ЛЦД5110_Грапх.х> //хттп://ввв.ринкидинкелецтроницс.цом/либрари.пхп?ид=48


#инцлуде <АТ24ЦКС.х> //хттпс://гитхуб.цом/циберп/АТ24Цк
#инцлуде <Вире.х> //Ардуино ИДЕ укључен
#инцлуде <РДСПарсер.х> //хттп://ввв.матхертел.де/Ардуино/РадиоЛибрари.аспк
#инцлуде <радио.х> //хттп://ввв.матхертел.де/Ардуино/РадиоЛибрари.аспк
#инцлуде <РТЦлиб.х> //хттпс://гитхуб.цом/адафруит/РТЦлиб
#инцлуде <РДА5807М.х> //хттп://ввв.матхертел.де/Ардуино/РадиоЛибрари.аспк
#инцлуде <Кеипад.х> //хттп://плаигроунд.ардуино.цц/Цоде/Кеипад
#дефине МАКСмени 4
#дефини ледПин 13
#дефине блПин 7

//дефинишемо цимболе на дугмадима тастатура


цхар тастери [ 7 ][ 2 ] = {
{ 'Л' , 'П' }, //ЛЕД, ПОВЕР
{ 'И' , 'Д' }, //ИНФО, ДИСПЛАИ
{ '1' , '2' }, //пресет
{ '3' , '4' }, //од 1
{ '5' , '6' }, //до 6
{ 'М' , 'м' }, //МОДЕ, МЕМ
{ '<' , '>' } //доле, горе
};
byte rowPins[7] = {11, 12, 10, 17, 9, 16, 8}; //connect to the row pinouts of the keypad
byte colPins[2] = {15, 14}; //connect to the column pinouts of the keypad

//Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, 7, 2 );

boolean bass = 0, dspl = 0, memdisplay = 0, mempress = 0, adj = 0;


boolean ledPin_state, power_state;
int menu;
int volume, volumeOld = 5;
int frequency, frequencyOld;
int txtl = 0, temparray = 0;
int samples[5];
unsigned int status[6];
unsigned long timeprevious = 0, timeprev = 0;

// EEPROM object
AT24CX mem;

RTC_DS1307 rtc;

//(clk, din, dc, ce, rst)


LCD5110 lcd(6, 5, 4, 2, 3);

// Create an instance of a RDA5807 chip radio


RDA5807M radio;

/// get a RDS parser


RDSParser rds;

extern unsigned char SmallFont[];


extern uint8_t signal5[];
extern uint8_t signal4[];
extern uint8_t signal3[];
extern uint8_t signal2[];
extern uint8_t signal1[];

//--------------------------SETUP----------------------------------//
void setup()
{
analogReference(EXTERNAL);
Serial.begin(9600);
Wire.begin();

// Initialize the Radio


radio.init();
radio.debugEnable();

//initialize the Screen


lcd.InitLCD();
lcd.clrScr();
//lcd.setContrast(45); //adjust if default isn't good
lcd.setFont(SmallFont);
lcd.enableSleep(); //stand-by mode

power_state = 0; //don't "power-on" of the unit (stand by mode) when power supply is connected

//inicialize the keyboard


keypad.addStatedEventListener(keypadEvent); // Add an event listener for this keypad
keypad.setHoldTime(1500);

pinMode(ledPin, OUTPUT); // Sets the digital pin as output.


pinMode(blPin, OUTPUT); // Sets the digital pin as output.
digitalWrite(ledPin, LOW); // Turn the LED off.
digitalWrite(blPin, LOW); // Turn the BL off (stand-by mode)
ledPin_state = digitalRead(ledPin); // Store initial LED state. HIGH when LED is on.

//uncomment if rtc need to be adjusted


/*if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2018, 3, 13, 22, 33, 0));
}*/

// read value of last frequency


frequency = mem.readInt(201);

volume = 2; //volume level at start


menu = 1; //shows VOLUMME mode at start

if (volume < 0) volume = 0;


if (volume > 15) volume = 15;
if (frequency < 0) frequency = 0;
if (frequency > 210) frequency = 210;

WriteReg(0x02, 0xC00d); // write 0xC00d into Reg.2 ( soft reset, enable,RDS, ) //bbz
canal(frequency);

// setup the information chain for RDS data.


radio.attachReceiveRDS(RDS_process);
rds.attachServicenNameCallback(DisplayServiceName);
//rds.attachTimeCallback(DisplayTime); //for future use. very inaccurate when RDS signal is weak.
rds.attachTextCallback(DisplayText);
}

//-----------------------end of Setup------------------------------------//

//--------------------------LOOP----------------------------------------//

void loop()
{
if ( frequency != frequencyOld)
{
frequencyOld = frequency;
mem.writeInt(201, frequency);
canal(frequency);
}

if (volume != volumeOld)
{
volumeOld = volume;
WriteReg(5, 0x84D0 | volume);
}

//read the keyboard


char key = keypad.getKey();

//check for RDS data


radio.checkRDS();

// reads temperature probe every 0,6 sec 5 times and calculates average
float average;
unsigned long timenow = millis();
if ((unsigned long)(timenow - timeprevious) > 600) {
timeprevious = timenow;
samples[temparray] = analogRead(A7);
temparray++;
}
if (temparray == 5) {
// calculating average of readings
average = 0;
for (int i = 0; i < 5; i++) {
average += samples[i];
}
printTemp(average);
temparray = 0;
}

// 4 sec timeout for MEM display and enter


unsigned long dabar = millis();
if (mempress == 1) {
timeprev = dabar;
memdisplay = 1;
mempress = 0;
}
if (memdisplay == 1) {
if ((unsigned long)(dabar - timeprev) < 4000) {
memdisplay = 1;
}
else {
memdisplay = 0;
}
}

/*Time adjustment instructions:


1. Run serial monitor
2. Set 9600 boud
3. Hit enter to activate serial reading
4. Write hXX, where XX is current hour reading on some time server and hit enter to adjust RTC hours. Serial monitor should write "Hours XX"
5. Write mXX, where XX is current minutes reading on some time server and hit enter to adjust RTC minutes. Serial monitor should write "Minutes XX"
6. Write sXX, where XX is current seconds reading on some time server and hit enter to adjust RTC seconds. Serial monitor should write "Seconds XX"
7. You can adjust only hours. I.e. when day light saving time was changed.
8. You can adjust only seconds if you need to correct time only.
9. If RTC has to be adjusted from zero (year, month, day, etc), uncomment RTC adjustment statement lines and upload the sketch.
*/
DateTime now = rtc.now();
if (Serial.available() > 0) {
char t = Serial.read();
switch (t) {
case ('h'): {
unsigned int hours = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hours, now.minute(), now.second()));
Serial.println(F("Hours"));
Serial.println(hours);
break;
}
case ('m'): {
unsigned int mins = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), mins, now.second()));
Serial.println(F("Minutes"));
Serial.println(mins);
break;
}
case ('s'): {
unsigned int sec = Serial.parseInt();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), sec));
Serial.println(F("Seconds"));
Serial.println(sec);
break;
}
}
}

//display various information on LCD


printSignalStrength();
printLines();

printTime();
printFreq();
printStereo();
printMode();
printMenu();
printDate();
lcd.update();
}
//------------------------End of Loop------------------------------------//

void printSignalStrength() //from 0000 to 1111 (0-63)


{
unsigned int sig;
Readstatus();
sig = status[1] / 1000;
if ((sig >= 0) && (sig <= 12)) {
lcd.drawBitmap(1, 1, signal1, 17 , 6);
}
if ((sig >= 13) && (sig <= 24)) {
lcd.drawBitmap(1, 1, signal2, 17 , 6);
}
if ((sig >= 25) && (sig <= 36)) {
lcd.drawBitmap(1, 1, signal3, 17 , 6);
}
if ((sig >= 37) && (sig <= 48)) {
lcd.drawBitmap(1, 1, signal4, 17 , 6);
}
if (sig >= 49) {
lcd.drawBitmap(1, 1, signal5, 17 , 6);
}
}

void printLines()
{
lcd.drawLine(0, 9, 84, 9);
lcd.drawLine(0, 39, 84, 39);
}

void printTemp(float average) //could be optimised :)


{
average /= 5;
average = 1023 / average - 1;
average = 51700 / average;

float steinhart;
steinhart = average / 50000; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= 3950; // 1/B * ln(R/Ro)
steinhart += 1.0 / (25 + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // invert
steinhart -= 273.15; // celsius conversion

int tmp = round(steinhart);


lcd.printNumI(tmp, 60, 1, 2);
lcd.print(F("~C"), 72, 1);
}

/// Update the ServiceName text on the LCD display when in RDS mode.
void DisplayServiceName(char *name)
{
lcd.print(name, 18, 22);
}

void DisplayText(char *text)


{
//scroll second RDS line
lcd.print(text, txtl, 30);
txtl = txtl - 66;
if (txtl == -396) txtl = 0;
}

void printTime()
{
DateTime now = rtc.now();
lcd.printNumI(now.hour(), 24, 1, 2, '0');
lcd.print(":", 36, 1);
lcd.printNumI(now.minute(), 42, 1, 2, '0');
}

void printDate()
{
if (dspl == 1) { //checks if display key was pressed
ClearRDS();
DateTime now = rtc.now();
lcd.printNumI(now.year(), 12, 22, 4);
lcd.print(".", 36, 22);
lcd.printNumI(now.month(), 42, 22, 2, '0');
lcd.print(".", 54, 22);
lcd.printNumI(now.day(), 60, 22, 2, '0');

int dw = now.dayOfTheWeek();
switch (dw) {
case 0:
lcd.print(F("Sekmadienis"), CENTER, 30); //sunday F() macro to save sdram
break;
case 1:
lcd.print(F("Pirmadienis"), CENTER, 30); //monday etc...
break;
case 2:
lcd.print(F("Antradienis"), CENTER, 30);
break;
case 3:
lcd.print(F("Treciadienis"), CENTER, 30);
break;
case 4:
lcd.print(F("Ketvirtadienis"), CENTER, 30);
break;
case 5:
lcd.print(F("Penktadienis"), CENTER, 30);
break;
case 6:
lcd.print(F("Sestadienis"), CENTER, 30);
break;
}
lcd.update();
delay(4000); //not optimal
ClearRDS();
dspl = 0;
}
}

void printMode()
{
lcd.print(F("MODE "), 0, 41);
}

void printMenu()
{
if (menu == 1) {
lcd.print(F("VOLUME "), 30, 41);
if (volume < 0) {
lcd.print(F("XX"), 72, 41);
}
else
lcd.printNumI(volume + 1, 72, 41, 2, '0');
}
if (menu == 2) {
lcd.print(F("AUTO-TUNE"), 30, 41);
}
if (menu == 3) {
lcd.print(F("MAN.-TUNE"), 30, 41);
}
if (menu == 4) {
lcd.print(F(" BASS "), 30, 41);
if (bass == 0) {
lcd.print(F("OFF"), 66, 41);
}
else
lcd.print(F(" ON"), 66, 41);

}
}

void printFreq() //displays current frequency


{
int frHundr, frDec;
unsigned int fr;
fr = 870 + frequency;
frHundr = fr / 10;
frDec = fr % 10;
lcd.printNumI(frHundr, 30, 12, 3);
lcd.print(F("."), 48, 12);
lcd.printNumI(frDec, 54, 12, 1);
lcd.print(F("MHz"), 66, 12);
}

void printStereo()
{
if (memdisplay == 1) { //if MEM key was pressed
lcd.print(F("MEM>"), 0, 12);
}
//Stereo detection
else if ((status[0] & 0x0400) == 0)
lcd.print(F("( )"), 0, 12); //means MONO
else
lcd.print (F("(ST)"), 0, 12); //means STEREO
}

void search(byte direc) //automatic seek


{
byte i; //seek up or down
if (!direc) WriteReg(0x02, 0xC30d);
else WriteReg(0x02, 0xC10d);

for (i = 0; i < 10; i++) {


delay(200);
Readstatus();
if (status[0] & 0x4000)
{
frequency = status[0] & 0x03ff;
break;
}
}
}

void canal( int canal) //direct frequency


{
byte numberH, numberL;
numberH = canal >> 2;
numberL = ((canal & 3) << 6 | 0x10);
Wire.beginTransmission(0x11);
Wire.write(0x03);
Wire.write(numberH); // write frequency into bits 15:6, set tune bit
Wire.write(numberL);
Wire.endTransmission();
}

//RDA5807_adrs=0x10;
// I2C-Address RDA Chip for sequential Access
int Readstatus()
{
Wire.requestFrom(0x10, 12);
for (int i = 0; i < 6; i++) {
status[i] = 256 * Wire.read () + Wire.read();
}
Wire.endTransmission();

}
//RDA5807_adrr=0x11;
// I2C-Address RDA Chip for random Access
void WriteReg(byte reg, unsigned int valor)
{
Wire.beginTransmission(0x11);
Wire.write(reg); Wire.write(valor >> 8); Wire.write(valor & 0xFF);
Wire.endTransmission();
//delay(50);
}

void RDS_process(uint16_t block1, uint16_t block2, uint16_t block3, uint16_t block4) {


rds.processData(block1, block2, block3, block4);
}
void ClearRDS()
{
lcd.print(" ", 0, 22);
lcd.print(" ", 0, 30);
}

// Taking care of some special events.


void keypadEvent(KeypadEvent key, KeyState kpadState ) {
switch (kpadState) {
/*
Another way to adjust time:
1. Press and hold key D for at least 2 sec, when you hear hour ending time signals, or see last hour seconds
on some accurate clock.
2. Release key D to adjust hh.00.00.
3. Ahter adjustment, if your clock was late from 15 to 1 minutes, minutes and seconds will be 00
and hours will be increased by 1.
4. If your clock was hurry from 1 to 15 minutes, only minutes and seconds will be 00.
*/
case HOLD:
if (key == 'D' && power_state == 1) {
adj = 1;
}
break;
case RELEASED:
if (key == 'D' && adj == 1) {
DateTime now = rtc.now();
if (now.minute() >= 45 && now.minute() <= 59) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, 0, 0));
}
if (now.minute() >= 1 && now.minute() <= 15) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 0, 0));
}
adj = 0;
}
break;
case PRESSED:
if (key == 'M' && power_state == 1) {
memdisplay = 0;
menu++;
if (menu > MAXmenu)menu = 1;
}

if (key == '>' && power_state == 1) {


memdisplay = 0;
switch (menu)
{
case 1:
if (volume < 0) {
if (bass == 0) {
WriteReg(0x02, 0xD00D);
volume = 0;
}
if (bass == 1) {
WriteReg(0x02, 0xC00D);
volume = 0;
}
}
else
volume++;

if (volume > 15)volume = 15;


break;
case 2:
search(0);
ClearRDS();
break;
case 3:
frequency++;
if (frequency > 210)frequency = 210; // upper frequency limit
ClearRDS();
break;
case 4:
if (bass == 0) {
bass = 1;
WriteReg(0x02, 0xD00D);
}
break;
}
}

if (key == '<' && power_state == 1) {


memdisplay = 0;
switch (menu)
{
case 1:
volume--;
if (volume < 0) {
WriteReg(0x02, 0x800D);
//volume = 0;
}
break;
case 2:
search(1);
ClearRDS();
break;
case 3:
frequency--;
if (frequency < 0)frequency = 0;
ClearRDS();
break;
case 4:
if (bass == 1) {
bass = 0;
WriteReg(0x02, 0xC00D);
}
break;
}
}
// LED lights on/off
if (key == 'L' && power_state == 1) {
digitalWrite(ledPin, !digitalRead(ledPin));
ledPin_state = digitalRead(ledPin); // Remember LED state, lit or unlit.
}
// turns "power" on or off (stand-by mode)
if (key == 'P')
{
digitalWrite(blPin, !digitalRead(blPin));
power_state = digitalRead(blPin);
if (power_state == 0) {
lcd.enableSleep();
digitalWrite(ledPin, LOW);
}
else lcd.disableSleep();
volume = 2;
menu = 1;
}

if (key == '1' && power_state == 1) {


switch (memdisplay) {
case 0:
frequency = mem.readInt(110);
ClearRDS();
break;
case 1:
mem.writeInt(110, frequency);
memdisplay = 0;
break;

}
}
if (key == '2' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(120);
ClearRDS();
break;
case 1:
mem.writeInt(120, frequency);
memdisplay = 0;
break;

}
}
if (key == '3' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(130);
ClearRDS();
break;
case 1:
mem.writeInt(130, frequency);
memdisplay = 0;
break;

}
}
if (key == '4' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(140);
ClearRDS();
break;
case 1:
mem.writeInt(140, frequency);
memdisplay = 0;
break;

}
}
if (key == '5' && power_state == 1) {
switch (memdisplay) {
case 0:
frequency = mem.readInt(150);
ClearRDS();
break;
case 1:
mem.writeInt(150, frequency);
memdisplay = 0;
break;
}
}

if (key == '6' && power_state == 1) {


switch (memdisplay) {
case 0:
frequency = mem.readInt(160);
ClearRDS();
break;
case 1:
mem.writeInt(160, frequency);
memdisplay = 0;
break;
}
}

иф ( кључ == 'м' && повер_стате == 1 ) {


мемпресс = 1 ;
}
остало {
мемпресс = 0 ;
}

иф ( кеи == 'И' && повер_стате == 1 ) {


дспл = 1 ;
}
бреак ;
}
}

Цредитс

Саулиус Бандзевичиус
1 пројекат • 88 пратилаца
ПратитиКонтакт

Коментари
Пишите Преглед

пошта

Луиги Провенза
Пре 5 година
Одличан пројекат! Изгледа веома лепо.

 Захвалити

 Одговорити

Саулиус Бандзевичиус
Пре 5 година
Хвала вам!

 Захвалити

 Одговорите на разговор

ОС БУЛУТ
пре 4 године
Добијам следећу грешку приликом компајлирања.
Класична тастатура нема меммернамедаддстацед Евентлистер
Како да то поправим?

 Захвалити

 Одговорити

 1 хвала

Саулиус Бандзевичиус
пре 4 године
Ос Булут
Извињавам се због касног одговора. Не добијам сва обавештења о коментарима.
Да ли сте решили проблем?

 Захвалити

 Одговорите на разговор

 1 хвала

дсанду
пре 3 године
Господине САУЛИУС,
радим на спровођењу овог експеримента "ФМ радија", дизајнирао сам штампано коло, али сам имао неке софтверске проблеме који су решени.
Ко троши ресурсе меморије???
Може ли се нешто учинити?
Хвала!

 Захвалити

 Одговорити

 1 хвала

Саулиус Бандзевичиус
пре 3 године
Драги дсанду,
Мислим да су највећи потрошачи меморије ЛЦД библиотека, записи на ЛЦД-у, записи на серијском порту. Због ограничене меморије нисам
имплементирао подешавање сата.
Да ли сте завршили овај пројекат?
 Захвалити

 Одговорите на разговор

рандируе
пре годину дана
Ово изгледа сјајно! Можете ли ми рећи како сте смислили да добијете и прикажете РДС информације? Тражим примере на мрежи за РДА5807М и
користим библиотеку радио.х и ваш код је најкомплетнији који сам нашао. Копирао сам ваше функције РДС_процесс, ДисплаиСервицеНаме и
ДисплаиТект. Укључио сам три „прикачи“ позива у своје подешавање и позив за проверу РДС-а у петљу. Али никада не добијам текст у СервицеНаме
или Тект. Да ли сам у праву када претпостављам да би цхецкРДС требало да извуче све постојеће информације или треба да радим нешто
друго? Такође, видим да пишете директно на радио чип са:
ВритеРег(0к02, 0кЦ00д); // уписати 0кЦ00д у Рег.2 (софт ресет, енабле,РДС,) //ббз
Да ли је то некако неопходно?
Надам се да ћу се чути од вас, био бих захвалан на било каквој помоћи.

You might also like