Back to start
// =============================================================================================================================
/*
This Arduino code controls the ATMEGA328 chip on the PCB board that controls the 24 LED strips of the Word Clock
Attached to this PCB are
- RCT DS3231 ZS-042 clock module
- KY-040 Keyes Rotary Encoder
- LDR light sensor 5528
- Bluetooth RF Transceiver Module HC05
- DCF77 module DCF-2
- FM Stereo Radio Module RDA5807M RRD-102V2.0
A 74HC595 ULN2803APG combination regulates the LEDs by shifting in bits into the 74HC595 LED are turn On or Off
A FT232RL 5.5V FTDI USB to TTL Serial Module can be attached to program te ATMEGA and read the serial port
The HC05 Bluetooth module is use to read and write information or instructions to the clock
The DCF77 module can be attached to adjust the time to the second with German longwave time signal received by the module
The FM-module can be used to read the RDS-time from radio station or to play FM-radio station from within the clock
Title ..: Woordklok
Author .: Ed Nieuwenhuys
Changes.: 0.27-->0.40 read clock every second instead of every hour"
Changes.: 0.27-->0.40 Encoder turn writes time directly to clock"
Changes.: 0.42 toggle HetWasIs"
Changes.: 0.43 Added PWM on Pin5 to control dimming "
Changes.: 0.48 Minor changes"
Changes.: 0.49 rotary encoder improved"
Changes.: 0.50 Stable and organised coding"
Changes.: 0.51 (SQRT (long)analog read * 63.5) for less lineair dimming"
Changes.: 0.52 Changed rotary pins"
Changes.: 0.54 Coding voor Klok 3 en 5"
Changes.: 0.60 Nieuwe display format. Hetiswas na 10 sec uit "
Changes.: 0.61 Pinchanges"
Changes.: 0.63 Ebben klok No13"
Changes.: 0.64 Light reducer added"
Changes.: 0.65 Programma aangepast voor standaard front en KY-040 rotary-besturing ingebouwd"
Changes.: 0.66 Random tijd when no RTC signal"
Changes.: 0.67 Source code cleaning"
Changes.: 0.69 Bluetooth added"
Changes.: 0.70 Temperature added"
Changes.: 0.76 Rotary delay 200 ---> 0 ms"
Changes.: 0.78 BT Lightintensity"
Changes.: 0.79 FM-radio time and serial/bluetooth input commands added"
Changes.: 0.81 DCF77 receiver included"
Changes.: 0.84 #ifdef included statements in source file, optimisation of code"
Changes.: 0.86 English display added"
Changes.: 0.87 French display added ---> Failed text does not fit in 11 x 11 character matrix.
Changes.: 0.90 Dutch-English version"
*/
// ===============================================================================================================================
//--------------------------------------------
// ARDUINO Definition of installed modules
//--------------------------------------------
//#define FMRADIOMOD // in development time retrieval works. Needs automatic optimal sender search function
#define BLUETOOTHMOD
#define DCFMOD
#define ROTARYMOD
//--------------------------------------------
// ARDUINO Definition of installed language word clock
//--------------------------------------------
#define NL
// #define UK
// #define DE
// #define FR // in development
//--------------------------------------------
// ARDUINO Includes defines and initialysations
//--------------------------------------------
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>
#include "Time.h"
#ifdef BLUETOOTHMOD
#include <SoftwareSerial.h> // for Bluetooth communication
#endif BLUETOOTHMOD
#ifdef ROTARYMOD
#include <Encoder.h>
#endif ROTARYMOD
#ifdef DCFMOD
#include "DCF77.h"
#endif DCFMOD
#ifdef NL
#define HET Tekstprint("Het "); Display1=Display1 | (Toggle_HetWasIs<<0)
#define IS Tekstprint("is "); Display1=Display1 | (Toggle_HetWasIs<<1)
#define WAS Tekstprint("was "); Display1=Display1 | (Toggle_HetWasIs<<2)
#define MVIJF Tekstprint("vijf "); Display1=Display1 | (1<<3)
#define MTIEN Tekstprint("tien "); Display1=Display1 | (1<<4)
#define KWART Tekstprint("kwart "); Display1=Display1 | (1<<5)
#define VOOR Tekstprint("voor "); Display1=Display1 | (1<<6)
#define OVER Tekstprint("over "); Display1=Display1 | (1<<7)
#define PRECIES Tekstprint("precies "); Display2=Display2 | (1<<0)
#define HALF Tekstprint("half "); Display2=Display2 | (1<<1)
#define ELF Tekstprint("elf "); Display2=Display2 | (1<<2)
#define VIJF Tekstprint("vijf "); Display2=Display2 | (1<<3)
#define TWEE Tekstprint("twee "); Display2=Display2 | (1<<4)
#define EEN Tekstprint("een "); Display2=Display2 | (1<<5)
#define VIER Tekstprint("vier "); Display2=Display2 | (1<<6)
#define TIEN Tekstprint("tien "); Display2=Display2 | (1<<7)
#define TWAALF Tekstprint("twaalf "); Display3=Display3 | (1<<0)
#define DRIE Tekstprint("drie "); Display3=Display3 | (1<<1)
#define NEGEN Tekstprint("negen "); Display3=Display3 | (1<<2)
#define ACHT Tekstprint("acht "); Display3=Display3 | (1<<3)
#define ZES Tekstprint("zes "); Display3=Display3 | (1<<4)
#define ZEVEN Tekstprint("zeven "); Display3=Display3 | (1<<5)
#define UUR Tekstprint("uur "); Display3=Display3 | (1<<6)
#define EDSOFT Tekstprint("Edsoft "); Display3=Display3 | (1<<7)
#endif NL
#ifdef UK
#define HET Tekstprint("It "); Display1=Display1 | (Toggle_HetWasIs<<0)
#define IS Tekstprint("is "); Display1=Display1 | (Toggle_HetWasIs<<1)
#define WAS Tekstprint("was "); Display1=Display1 | (Toggle_HetWasIs<<2)
#define PRECIES Tekstprint("exact "); Display1=Display1 | (1<<3)
#define HALF Tekstprint("half "); Display1=Display1 | (1<<4)
#define TWINTIG Tekstprint("twenty "); Display1=Display1 | (1<<5)
#define MVIJF Tekstprint("five "); Display1=Display1 | (1<<6)
#define KWART Tekstprint("quarter "); Display1=Display1 | (1<<7)
#define MTIEN Tekstprint("ten "); Display2=Display2 | (1<<0)
#define OVER Tekstprint("past "); Display2=Display2 | (1<<1)
#define ZES Tekstprint("six "); Display2=Display2 | (1<<2)
#define TWEE Tekstprint("two "); Display2=Display2 | (1<<3)
#define VIJF Tekstprint("five "); Display2=Display2 | (1<<4)
#define TWAALF Tekstprint("twelve "); Display2=Display2 | (1<<5)
#define TIEN Tekstprint("ten "); Display2=Display2 | (1<<6)
#define ELF Tekstprint("eleven "); Display2=Display2 | (1<<7)
#define VIER Tekstprint("four "); Display3=Display3 | (1<<0)
#define NEGEN Tekstprint("nine "); Display3=Display3 | (1<<1)
#define DRIE Tekstprint("three "); Display3=Display3 | (1<<2)
#define ACHT Tekstprint("eight "); Display3=Display3 | (1<<3)
#define ZEVEN Tekstprint("seven "); Display3=Display3 | (1<<4)
#define EEN Tekstprint("one "); Display3=Display3 | (1<<5)
#define UUR Tekstprint("O'clock "); Display3=Display3 | (1<<6)
#define VOOR Tekstprint("to "); Display3=Display3 | (1<<7)
#endif UK
#ifdef FR
#define HET Tekstprint("Il "); Display1=Display1 | (Toggle_HetWasIs<<0)
#define IS Tekstprint("est "); Display1=Display1 | (Toggle_HetWasIs<<1)
#define WAS Tekstprint("etait "); Display1=Display1 | (Toggle_HetWasIs<<2)
#define ELF Tekstprint("onze "); Display1=Display1 | (1<<3)
#define VIJF Tekstprint("cing "); Display1=Display1 | (1<<4)
#define TWEE Tekstprint("deux "); Display1=Display1 | (1<<5)
#define DRIE Tekstprint("trois "); Display1=Display1 | (1<<6)
#define ZES Tekstprint("six "); Display1=Display1 | (1<<7)
#define VIER Tekstprint("quatre "); Display2=Display2 | (1<<0)
#define NTWAALF Tekstprint("minuit "); Display2=Display2 | (1<<1)
#define TIEN Tekstprint("dix "); Display2=Display2 | (1<<2)
#define NEGEN Tekstprint("neuf "); Display2=Display2 | (1<<3)
#define TWAALF Tekstprint("midi "); Display2=Display2 | (1<<4)
#define ACHT Tekstprint("huit "); Display2=Display2 | (1<<5)
#define ZEVEN Tekstprint("sept "); Display2=Display2 | (1<<6)
#define EEN Tekstprint("une "); Display2=Display2 | (1<<7)
#define UUR Tekstprint("heures "); Display3=Display3 | (1<<0)
#define OVER Tekstprint("et "); Display3=Display3 | (1<<1)
#define VOOR Tekstprint("moins "); Display3=Display3 | (1<<2)
#define EN Tekstprint("le "); Display3=Display3 | (1<<3)
#define KWART Tekstprint("quart "); Display3=Display3 | (1<<4)
#define MTIEN Tekstprint("dix "); Display3=Display3 | (1<<5)
#define TWINTIG Tekstprint("vingt "); Display3=Display3 | (1<<6)
#define MVIJF Tekstprint("cing "); Display3=Display3 | (1<<7)
#define HALF Tekstprint("demie "); TIEN; TWINTIG;
#endif FR
//--------------------------------------------
// PIN Assigments
//--------------------------------------------
// Digital hardware constants ----
enum DigitalPinAssignments {
DCF_PIN = 2, // DCFPulse on interrupt pin
encoderPinA = 3, // right (labeled DT on decoder)on interrupt pin
clearButton = 4, // switch (labeled SW on decoder)
PWMpin = 5, // Pin that controle PWM signal on BC327 transistor to dim light
BT_RX = 6, // Bluetooth RX
BT_TX = 7, // Bluetooth TX
encoderPinB = 8, // left (labeled CLK on decoder)no interrupt pin
DCF_LED_Pin = 9, // define pin voor AM PM Led
LEDDataPin = 10, // blauw HC595
LEDStrobePin = 11, // groen HC595
LEDClockPin = 12, // geel HC595
secondsPin = 13};
// Analogue hardware constants ----
enum AnaloguePinAssignments {
PhotoCellPin = 2, // LDR pin
EmptyA3 = 3, //
SDA_pin = 4, // SDA pin
SCL_pin = 5}; // SCL pin
//--------------------------------------------
// LED
//--------------------------------------------
byte BrightnessCalcFromLDR = 200; // BRIGHTNESS 0 - 255
//--------------------------------------------
// KY-040 ROTARY
//--------------------------------------------
Encoder myEnc(encoderPinA, encoderPinB); // Use digital pin for encoder
long Looptime = 0;
unsigned long RotaryPressTimer = 0;
//--------------------------------------------
// LDR PHOTOCELL
//--------------------------------------------
float LightReducer = 0.80 ; // Factor to dim ledintensity with. Between 0.1 and 1 in steps of 0.05
byte LowerBrightness = 10; // Lower limit of Brightness ( 0 - 255)
int OutPhotocell; // stores reading of photocell;
int MinPhotocell = 1024; // stores minimum reading of photocell;
int MaxPhotocell = 1; // stores maximum reading of photocell;
//--------------------------------------------
// CLOCK
//--------------------------------------------
static unsigned long msTick; // the number of millisecond ticks since we last incremented the second counter
int count;
int Delaytime = 200;
byte Display1 = 0, Display2 = 0, Display3 = 0;
byte Isecond, Iminute, Ihour, Iday, Imonth, Iyear;
byte lastminute = 0, lasthour = 0, sayhour = 0;
byte Toggle_HetWasIs = 1; // Turn On/Off HetIsWas lights
byte Toggle_HetWasIsUit = 0; // Turn off HetIsWas after 10 sec
byte SecPulse = 0; // give a pulse to the Isecond led
byte Demo = false;
String SerialString;
//--------------------------------------------
// DS3231 CLOCK MODULE
//--------------------------------------------
#define DS3231_I2C_ADDRESS 0x68
#define DS3231_TEMPERATURE_MSB 0x11
#define DS3231_TEMPERATURE_LSB 0x12
RTC_DS3231 RTC; //RTC_DS1307 RTC;
DateTime Inow;
//--------------------------------------------
// BLUETOOTH
//--------------------------------------------
#ifdef BLUETOOTHMOD // Bluetooth ---------------------
SoftwareSerial Bluetooth(BT_RX, BT_TX); // RX, TX
String BluetoothString;
#endif BLUETOOTHMOD
//--------------------------------------------
// RDA5807 FM-RADIO
//--------------------------------------------
#ifdef FMRADIOMOD // FM radio -----------------------
byte RadioUur; // reading from RDS FM-radio
byte RadioMinuut; // reading from RDS FM-radio
float fini = 103.50; //91.60; // 103.50; //98.10; // Start frequency
int ftun; // Selected frequency
float Freq_lower_bandwith = 87.00;// lower Band limit
float Freq_tuned; //
int RDA5807_adrs = 0x10; // I2C-Address RDA Chip for sequential Access
int RDA5807_adrr = 0x11; // I2C-Address RDA Chip for random Access
int RDA5807_adrt = 0x60; // I2C-Address RDA Chip for TEA5767like Access
int sidx = 0; // Counter of frequency array
int vol = 0; // Volume
int rssi = 0; // Signal-Level
unsigned int auRDS[32];
unsigned int auRDA5807_Reg[32];
unsigned int aui_RDA5807_Reg[32];
unsigned int aui_buf[8];
unsigned int auRDA5807_Regdef[10] ={
0x0758, // 00 defaultid
0x0000, // 01 not used
0xD009, // 02 DHIZ,DMUTE,BASS, POWERUPENABLE,RDS
0x0000, // 03
0x1400, // 04 DE ? SOFTMUTE
0x84D0, // 05 INT_MODE, SEEKTH=0110,????, Volume=0
0x4000, // 06 OPENMODE=01
0x0000, // 07 unused ?
0x0000, // 08 unused ?
0x0000 // 09 unused ?
};
#endif FMRADIOMOD // END FM radio ------------------------
//--------------------------------------------
// DCF-2 DCF77 MODULE
//--------------------------------------------
#ifdef DCFMOD // DCF77 ------------------------------
#define DCF_INTERRUPT 0 // DCF Interrupt number associated with DCF_PIN
time_t time;
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT,LOW);
#endif DCFMOD
// End Definitions ---------------------------------------------------------
//--------------------------------------------
// ARDUINO Loop
//--------------------------------------------
void loop(void)
{
SerialCheck();
if(Demo) Demomode();
else
{
#ifdef FMRADIOMOD
FMradioCheck();
#endif FMRADIOMOD
EverySecondCheck();
#ifdef DCFMOD
DCF77Check();
#endif DCFMOD
#ifdef BLUETOOTHMOD
BluetoothCheck();
#endif BLUETOOTHMOD
EveryMinuteUpdate();
#ifdef ROTARYMOD
RotaryEncoderCheck();
#endif ROTARYMOD
}
}
//--------------------------------------------
// ARDUINO Setup
//--------------------------------------------
void setup()
{ // initialise the hardware // initialize the appropriate pins as outputs:
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDStrobePin, OUTPUT);
pinMode(PWMpin, OUTPUT);
pinMode(DCF_LED_Pin, OUTPUT);
pinMode(secondsPin, OUTPUT );
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(clearButton, INPUT_PULLUP);
pinMode(DCF_PIN, INPUT_PULLUP);
Serial.begin(9600); // setup the serial port to 9600 baud
#ifdef BLUETOOTHMOD
Bluetooth.begin(9600); // setup the Bluetooth port to 9600 baud
#endif BLUETOOTHMOD
#ifdef FMRADIOMOD
Setup_FMradio(); // start the FM-radio
#endif FMRADIOMOD
#ifdef DCFMOD
DCF.Start(); // start the DCF-module
#endif DCFMOD
Wire.begin(); // start the wire communication I2C
RTC.begin(); // start the RTC-module
analogWrite(PWMpin, BrightnessCalcFromLDR); // the duty cycle: between 0 (lights off) and 255 (light full on).
DateTime now = RTC.now(); // Get the time from the RTC
DateTime compiled = DateTime(__DATE__, __TIME__);
if (now.unixtime() < compiled.unixtime())
{
Serial.println("RTC is older than compile time! Updating"); // following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (EEPROM.read(0) <10 || EEPROM.read(0) > 100)
EEPROM.write(0,(int)(LightReducer * 100)); // default intensity for this clock
if (EEPROM.read(1) <10 || EEPROM.read(1) > 100)
EEPROM.write(1, LowerBrightness); // default Lower Brightness for this clock
LightReducer = ((float) EEPROM.read(0) / 100); // store it is the work variable
LowerBrightness = EEPROM.read(1); // store it is the work variable
Looptime = millis(); // Used in KY-040 rotary
msTick = millis();
SWversion(); // Display the version number of the software
Selftest(); // Play the selftest
GetTijd(0); // Get the time and print it to serial
}
// --------------------------- END SETUP
//--------------------------------------------
// CLOCK Version info
//--------------------------------------------
void SWversion(void)
{
for (int n=0; n<90;n++) {Serial.print(F("="));} Serial.println();
Serial.println(F("Title ..........: Woordklok Peter Schnitzeler zwartwit met Rotary KY-040, Temp, Bluetooth, FM, DCF77"));
#ifdef BLUETOOTHMOD
Bluetooth.println(F("Woordklok Noxx first connected in 2016 "));
Bluetooth.println(F("Enter time as:hhmm (1321) or hhmmss (132145)"));
Bluetooth.println(F("Enter A for normal display"));
Bluetooth.println(F("Enter B to suspress Het Is Was in display"));
Bluetooth.println(F("Enter C to suspress Het Is Was after 10 seconds every minute change in display"));
Bluetooth.println(F("Enter D for Demo mode"));
Bluetooth.println(F("Enter Mnn (M90) to reduce light intensity to 90% range 5% - 100%"));
Bluetooth.println(F("Enter Lnn (L5) to set lowest intensity during darkness "));
Bluetooth.println(F("Enter I for info"));
#endif BLUETOOTHMOD
Serial.println(F("Author ......: Ed Nieuwenhuys"));
Serial.println(F("Version.........: 0.90 Juli-2016"));
Serial.print(F( "LightReducer....: ")); Serial.print(LightReducer*100); Serial.println(F("%"));
Serial.print(F( "LowerBrightness.: ")); Serial.println(LowerBrightness);
for (int n=0; n<90;n++) {Serial.print(F("="));} Serial.println();
}
//--------------------------------------------
// CLOCK Demo mode
//--------------------------------------------
void Demomode(void)
{
if ( millis() - msTick >50) digitalWrite(secondsPin,LOW); // Turn OFF the second on pin 13
if ( millis() - msTick >999) // Flash the onboard Pin 13 Led so we know something is happening
{
msTick = millis(); // second++;
digitalWrite(secondsPin,HIGH); // turn ON the second on pin 13
++SecPulse; // second routine in function DimLeds
if( ++Iminute >59) { Iminute = 0; Isecond = 0; Ihour++;}
if( Ihour >24) Ihour = 0;
DimLeds(false);
Displaytime();
}
}
//--------------------------------------------
// CLOCK common print routines
//--------------------------------------------
void Tekstprint(char tekst[])
{
Serial.print(tekst);
#ifdef BLUETOOTHMOD
Bluetooth.print(tekst);
#endif BLUETOOTHMOD
}
void Tekstprintln(char tekst[])
{
Serial.println(tekst);
#ifdef BLUETOOTHMOD
Bluetooth.println(tekst);
#endif BLUETOOTHMOD
}
//--------------------------------------------
// CLOCK Update routine done every second
//--------------------------------------------
void EverySecondCheck(void)
{
if ( millis() - msTick >50) digitalWrite(secondsPin,LOW); // Turn OFF the second on pin 13
if ( millis() - msTick >999) // Flash the onboard Pin 13 Led so we know something is happening
{
msTick = millis(); // second++;
digitalWrite(secondsPin,HIGH); // turn ON the second on pin 13
++SecPulse; // second routine in function DimLeds
GetTijd(0); // synchronize time with RTC clock
if ((Toggle_HetWasIsUit == 2) && (Isecond > 10)) Toggle_HetWasIs = 0;
else Toggle_HetWasIs = 1; // HET IS WAS is On
if(Isecond % 30 == 0) DimLeds(true); //Led Intensity Control + seconds tick print every 30 seconds
else DimLeds(false);
if ((Toggle_HetWasIsUit == 2) && (Isecond == 11))Displaytime(); // turn Leds OFF on second == 11
}
}
//--------------------------------------------
// CLOCK Update routine done every minute
//--------------------------------------------
void EveryMinuteUpdate(void)
{
if (Iminute != lastminute) //show time every minute
{
lastminute = Iminute;
Displaytime();
Print_RTC_tijd();
#ifdef BLUETOOTHMOD
Print_BTtijd(); // print time to Bluetooth
#endif BLUETOOTHMOD
}
if (Ihour != lasthour) {lasthour = Ihour;}
}
#ifdef BLUETOOTHMOD
//--------------------------------------------
// CLOCK check for Bluetooth input
//--------------------------------------------
void BluetoothCheck(void)
{
while (Bluetooth.available())
{
delay(3);
char c = Bluetooth.read();
if (c>31 && c<128) BluetoothString += c;
}
if (BluetoothString.length()>0) ReworkInputString(BluetoothString); // Rework ReworkInputString();
BluetoothString = "";
}
#endif BLUETOOTHMOD
#ifdef DCFMOD
//--------------------------------------------
// CLOCK check for DCF input
//--------------------------------------------
void DCF77Check(void)
{
time_t DCFtime = DCF.getTime(); // Check if new DCF77 time is available
if (DCFtime!=0)
{
Serial.print(F("Time is updated -----> "));
setTime(DCFtime);
RTC.adjust(DCFtime);
digitalClockDisplay();
}
digitalWrite(DCF_LED_Pin,1-digitalRead(DCF_PIN)); // write inverted DCF pulse to LED on board
}
#endif DCFMOD
//--------------------------------------------
// CLOCK check for serial input
//--------------------------------------------
void SerialCheck(void)
{
while (Serial.available())
{
delay(3);
char c = Serial.read();
if (c>31 && c<128) SerialString += c; // allow input from Space - Del
}
if (SerialString.length()>0) ReworkInputString(SerialString); // Rework ReworkInputString();
SerialString = "";
}
//------------------------ KY-040 rotary encoder -------------------------
//--------------------------------------------
// KY-040 ROTARY check if the rotary is moving
//--------------------------------------------
#ifdef ROTARYMOD
void RotaryEncoderCheck(void)
{
// If button pressed, 60 sec after start ATMEGA, then there are 60 seconds to adjust the light intensity.
// RotaryPressTimer is the time in millisec after start ATMEGA
long encoderPos = myEnc.read();
if ( (encoderPos) && ( (millis() - Looptime) >500)) // if rotary turned debounce 0.5 sec
{
Serial.print(F("--------> Index:")); Serial.println(encoderPos);
if (encoderPos >0) // increase the MINUTES
{
if ( millis() > 60000 && (millis() - RotaryPressTimer) < 60000)
{ WriteLightReducer(0.05); } // If time < 60 sec then adjust light intensity factor
else
{
if( ++Iminute >59) { Iminute = 0; Isecond = 0; }
SetRTCTime();
}
myEnc.write(0);
Looptime = millis(); // Set encoder pos back to 0
}
if (encoderPos <0) // increase the HOURS
{
if (millis() > 60000 && (millis() - RotaryPressTimer) < 60000)
{ WriteLightReducer(-0.05); } // If time < 60 sec then adjust light intensity factor
else
{
if( ++Ihour >23) { Ihour = 0; }
SetRTCTime();
}
myEnc.write(0);
Looptime = millis(); // Set encoder pos back to 0
}
}
if (digitalRead(clearButton) == LOW ) // set the time by pressing rotary button
{
delay(200);
RotaryPressTimer = millis(); // If time < 60 sec then adjust light intensity factor
Toggle_HetWasIsUit++;
if (Toggle_HetWasIsUit >= 3) { Toggle_HetWasIsUit = 0 ; }
if (Toggle_HetWasIsUit == 0) { Toggle_HetWasIs = 1;} // On
if (Toggle_HetWasIsUit == 1) { Toggle_HetWasIs = 0;} // Off
if (Toggle_HetWasIsUit == 2) { Toggle_HetWasIs = 0; Play_Lights(); } // Off after 10 sec
Serial.print(F("Toggle_HetWasIsUit: ")); Serial.println(Toggle_HetWasIsUit);
Serial.print(F("Toggle_HetWasIs: ")); Serial.println(Toggle_HetWasIs);
Displaytime();
myEnc.write(0);
Looptime = millis();
}
}
#endif ROTARYMOD
//--------------------------------------------
// CLOCK Self test sequence
//--------------------------------------------
void Selftest(void)
{
GetTijd(1); //Prints time in Serial monitor
LedsOff();
#ifdef NL
HET; Laatzien();
IS; Laatzien();
WAS; Laatzien();
MVIJF; Laatzien();
MTIEN; Laatzien();
KWART; Laatzien();
VOOR; Laatzien();
OVER; Laatzien();
PRECIES; Laatzien();
HALF; Laatzien();
ELF; Laatzien();
VIJF; Laatzien();
TWEE; Laatzien();
EEN; Laatzien();
VIER; Laatzien();
TIEN; Laatzien();
TWAALF; Laatzien();
DRIE; Laatzien();
NEGEN; Laatzien();
ACHT; Laatzien();
ZES; Laatzien();
ZEVEN; Laatzien();
UUR; Laatzien();
EDSOFT; Laatzien();
#endif NL
#ifdef UK
HET; Laatzien();
IS; Laatzien();
WAS; Laatzien();
PRECIES; Laatzien();
HALF; Laatzien();
TWINTIG; Laatzien();
MVIJF; Laatzien();
KWART; Laatzien();
MTIEN; Laatzien();
OVER; Laatzien();
VOOR; Laatzien();
ZES; Laatzien();
TWEE; Laatzien();
VIJF; Laatzien();
TWAALF; Laatzien();
TIEN; Laatzien();
ELF; Laatzien();
VIER; Laatzien();
NEGEN; Laatzien();
DRIE; Laatzien();
ACHT; Laatzien();
ZEVEN; Laatzien();
EEN; Laatzien();
UUR; Laatzien();
#endif UK
for(int i=0; i<2; i++)
{
Display1=255; Display2=255; Display3=255; Laatzien();
Display1=0; Display2=0; Display3=0; Laatzien();
}
Play_Lights();
Displaytime();
}
// -------------------------- END Selftest
//--------------------------- Time functions --------------------------
//--------------------------------------------
// CLOCK set the LED's for displaying
//--------------------------------------------
void Displaytime(void)
{
LedsOff(); // start by clearing the display to a known state
HET; // HET light is always on
switch (Iminute)
{
#ifdef NL
case 0: IS; PRECIES; break;
case 1: IS; break;
case 2:
case 3: WAS; break;
case 4:
case 5:
case 6: IS; MVIJF; OVER; break;
case 7:
case 8: WAS; MVIJF; OVER; break;
case 9:
case 10:
case 11: IS; MTIEN; OVER; break;
case 12:
case 13: WAS; MTIEN; OVER; break;
case 14:
case 15:
case 16: IS; KWART; OVER; break;
case 17:
case 18: WAS; KWART; OVER; break;
case 19:
case 20:
case 21: IS; MTIEN; VOOR; HALF; break;
case 22:
case 23: WAS; MTIEN; VOOR; HALF; break;
case 24:
case 25:
case 26: IS; MVIJF; VOOR; HALF; break;
case 27:
case 28: WAS; MVIJF; VOOR; HALF; break;
case 29: IS; HALF; break;
case 30: IS; PRECIES; HALF; break;
case 31: IS; HALF; break;
case 32:
case 33: WAS; HALF; break;
case 34:
case 35:
case 36: IS; MVIJF; OVER; HALF; break;
case 37:
case 38: WAS; MVIJF; OVER; HALF; break;
case 39:
case 40:
case 41: IS; MTIEN; OVER; HALF; break;
case 42:
case 43: WAS; MTIEN; OVER; HALF; break;
case 44:
case 45:
case 46: IS; KWART; VOOR; break;
case 47:
case 48: WAS; KWART; VOOR; break;
case 49:
case 50:
case 51: IS; MTIEN; VOOR; break;
case 52:
case 53: WAS; MTIEN; VOOR; break;
case 54:
case 55:
case 56: IS; MVIJF; VOOR; break;
case 57:
case 58: WAS; MVIJF; VOOR; break;
case 59: IS; break;
#endif NL
#ifdef UK
case 0: IS; PRECIES; break;
case 1: IS; break;
case 2:
case 3: WAS; break;
case 4:
case 5:
case 6: IS; MVIJF; OVER; break;
case 7:
case 8: WAS; MVIJF; OVER; break;
case 9:
case 10:
case 11: IS; MTIEN; OVER; break;
case 12:
case 13: WAS; MTIEN; OVER; break;
case 14:
case 15:
case 16: IS; KWART; OVER; break;
case 17:
case 18: WAS; KWART; OVER; break;
case 19:
case 20:
case 21: IS; TWINTIG; OVER; break;
case 22:
case 23: WAS; TWINTIG; OVER; break;
case 24:
case 25:
case 26: IS; TWINTIG; MVIJF; OVER; break;
case 27:
case 28: WAS; TWINTIG; MVIJF; OVER; break;
case 29: IS; HALF; OVER; break;
case 30: IS; PRECIES; HALF; OVER; break;
case 31: IS; HALF; OVER; break;
case 32:
case 33: WAS; HALF; OVER; break;
case 34:
case 35:
case 36: IS; TWINTIG; MVIJF; VOOR; break;
case 37:
case 38: WAS; TWINTIG; MVIJF; VOOR; break;
case 39:
case 40:
case 41: IS; TWINTIG; VOOR; break;
case 42:
case 43: WAS; TWINTIG; VOOR; break;
case 44:
case 45:
case 46: IS; KWART; VOOR; break;
case 47:
case 48: WAS; KWART; VOOR; break;
case 49:
case 50:
case 51: IS; MTIEN; VOOR; break;
case 52:
case 53: WAS; MTIEN; VOOR; break;
case 54:
case 55:
case 56: IS; MVIJF; VOOR; break;
case 57:
case 58: WAS; MVIJF; VOOR; break;
case 59: IS; break;
#endif UK
}
// if (Ihour >=0 && Ihour <12) digitalWrite(DCF_LED_Pin,0); else digitalWrite(DCF_LED_Pin,1);
#ifdef NL
sayhour = Ihour;
if (Iminute > 18 ) sayhour = Ihour+1;
if (sayhour == 24) sayhour = 0;
#endif NL
#ifdef UK
sayhour = Ihour;
if (Iminute > 33 ) sayhour = Ihour+1;
if (sayhour == 24) sayhour = 0;
#endif UK
switch (sayhour)
{
case 13:
case 1: EEN; break;
case 14:
case 2: TWEE; break;
case 15:
case 3: DRIE; break;
case 16:
case 4: VIER; break;
case 17:
case 5: VIJF; break;
case 18:
case 6: ZES; break;
case 19:
case 7: ZEVEN; break;
case 20:
case 8: ACHT; break;
case 21:
case 9: NEGEN; break;
case 22:
case 10: TIEN; break;
case 23:
case 11: ELF; break;
case 0:
case 12: TWAALF; break;
}
switch (Iminute)
{
case 59:
case 0:
case 1:
case 2:
case 3: UUR; break;
}
Tekstprintln("");
WriteLEDs();
}
//--------------------------------------------
// DS3231 Get time from DS3231
//--------------------------------------------
void GetTijd(byte printit)
{
Inow = RTC.now();
Ihour = Inow.hour();
Iminute = Inow.minute();
Isecond = Inow.second();
// if (Ihour > 24) { Ihour = random(12)+1; Iminute = random(60)+1; Isecond = 30;} // set a time if time module is absent or defect
if (printit) Print_RTC_tijd();
}
//--------------------------------------------
// DS3231 utility function prints time to serial
//--------------------------------------------
void Print_RTC_tijd(void)
{
Inow = RTC.now();
if (Inow.hour() < 10) Serial.print(F("0"));
Serial.print(Inow.hour(), DEC);
Serial.print(F(":"));
if (Inow.minute() < 10) Serial.print(F("0"));
Serial.print(Inow.minute(), DEC);
Serial.print(F(":"));
if (Inow.second() < 10) Serial.print(F("0"));
Serial.print(Inow.second(), DEC);
Serial.print(F(" "));
Serial.print(Inow.day(), DEC);
Serial.print(F("/"));
Serial.print(Inow.month(), DEC);
Serial.print(F("/"));
Serial.println(Inow.year(), DEC);
}
//--------------------------------------------
// CLOCK utility function prints time to serial
//--------------------------------------------
void Print_tijd(void)
{
if (Ihour < 10) Serial.print(F("0"));
Serial.print(Ihour);
Serial.print(F(":"));
if (Iminute < 10) Serial.print(F("0"));
Serial.print(Iminute);
Serial.print(F(":"));
if (Isecond < 10) Serial.print(F("0"));
Serial.println(Isecond);
}
//--------------------------------------------
// BLUETOOTH utility function prints time to BT
//--------------------------------------------
#ifdef BLUETOOTHMOD
void Print_BTtijd(void)
{
Bluetooth.print(F("T: "));
if (Ihour < 10) Bluetooth.print(F("0"));
Bluetooth.print(Ihour);
Bluetooth.print(F(":"));
if (Iminute < 10) Bluetooth.print(F("0"));
Bluetooth.print(Iminute);
Bluetooth.print(F(":"));
if (Isecond < 10) Bluetooth.print(F("0"));
Bluetooth.print(Isecond);
Bluetooth.print(F(" I:"));
Bluetooth.print(( int) (BrightnessCalcFromLDR/2.55));
Bluetooth.print(F("% LDR:"));
Bluetooth.print(analogRead(PhotoCellPin)/10);
Bluetooth.print(F("% T:"));
Bluetooth.print(get3231Temp());
Bluetooth.println(F("C"));
}
#endif BLUETOOTHMOD
#ifdef DCFMOD
//--------------------------------------------
// DCF77 utility function prints DCF time
//--------------------------------------------
void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(F(" "));
Serial.print(day());
Serial.print(F(" "));
Serial.print(month());
Serial.print(F(" "));
Serial.print(year());
Serial.println();
}
//--------------------------------------------
// DCF77 utility function prints preceding colon and leading 0
//--------------------------------------------
void printDigits(int digits)
{
Serial.print(F(":"));
if(digits < 10)
Serial.print(F("0"));
Serial.print(digits);
}
#endif DCFMOD
//--------------------------------------------
// DS3231 Set time in module and print it
//--------------------------------------------
void SetRTCTime(void)
{
RTC.adjust(DateTime(Inow.year(), Inow.month(), Inow.day(), Ihour, Iminute, Isecond));
GetTijd(0); // synchronize time with RTC clock
Displaytime();
Print_tijd();
}
//--------------------------------------------
// DS3231 Get temperature from module
//--------------------------------------------
int get3231Temp(void)
{
byte tMSB, tLSB;
int temp3231;
Wire.beginTransmission(DS3231_I2C_ADDRESS); //temp registers (11h-12h) get updated automatically every 64s
Wire.write(0x11);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
if(Wire.available())
{
tMSB = Wire.read(); //2's complement int portion
tLSB = Wire.read(); //fraction portion
temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
temp3231 += ( (tLSB >> 6) * 0.25 ) + 0.5; //only care about bits 7 & 8 and add 0.5 to round off to integer
}
else { temp3231 = -273; }
return (temp3231);
}
// ------------------- End Time functions
// --------------------Light functions -----------------------------------
//--------------------------------------------
// LED Clear display settings of the LED's
//--------------------------------------------
void LedsOff(void){ Display1=0; Display2=0; Display3=0; }
//--------------------------------------------
// LED Turn On the LED's
//--------------------------------------------
void WriteLEDs(void)
{ // Write the actual values to the hardware
digitalWrite(LEDStrobePin,LOW);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDStrobePin,HIGH);
delay(2);
Serial.print(Display1, BIN);
Serial.print(":");
Serial.print(Display2, BIN);
Serial.print(":");
Serial.println(Display3, BIN);
}
//--------------------------------------------
// LED Turn On en Off the LED's
//--------------------------------------------
void Laatzien()
{
WriteLEDs();
delay(Delaytime);
LedsOff();
}
//--------------------------------------------
// LED Dim the leds by PWM measured by the LDR and print values
//--------------------------------------------
void DimLeds(byte print)
{
if (SecPulse)
{
int LDR_read = analogRead(PhotoCellPin); // Read lightsensor
OutPhotocell = (int) (LightReducer * sqrt( (float) 63.5 * constrain(LDR_read,10,1023))); // filter out of strange results and set minimum brightness
MinPhotocell = MinPhotocell > LDR_read ? LDR_read : MinPhotocell;
MaxPhotocell = MaxPhotocell < LDR_read ? LDR_read : MaxPhotocell;
if(print)
{
Serial.print(F("SensorRead: ")); Serial.print(LDR_read);
Serial.print(F(" LightReducer: ")); Serial.print((int) (LightReducer * 100));
Serial.print(F("% Min: ")); Serial.print(MinPhotocell);
Serial.print(F(" Max: ")); Serial.print(MaxPhotocell);
Serial.print(F(" Now: ")); Serial.print(OutPhotocell);
}
BrightnessCalcFromLDR = constrain(OutPhotocell, LowerBrightness , 255); // filter out of strange results
if(print)
{
Serial.print(F(" LI Now: ")); Serial.print(( int) (BrightnessCalcFromLDR/2.55));
Serial.print(F("%"));
Serial.print(F(" Temp: ")); Serial.print(get3231Temp()); Serial.print(F("C "));
Print_tijd();
}
analogWrite(PWMpin, BrightnessCalcFromLDR); // write PWM
}
SecPulse = 0;
}
//--------------------------------------------
// LED Turn On en Off the LED's
//--------------------------------------------
void Play_Lights()
{
Display1=255; Display2=255; Display3=255; Laatzien();
for (int n=255 ; n>=0; n--) { analogWrite(PWMpin, n); delay(2);} // the duty cycle: between 0 (lights off) and 255 (light full on).
for (int n=0 ; n<=255; n++) { analogWrite(PWMpin, n); delay(2);}
LedsOff();
}
//--------------------------------------------
// LED In- or decrease light intensity value
//--------------------------------------------
void WriteLightReducer(float amount)
{
LightReducer += amount;
WriteLightReducerEeprom(LightReducer);
}
//--------------------------------------------
// LED Write light intensity to EEPROM
//--------------------------------------------
void WriteLightReducerEeprom(float value)
{
LightReducer = value;
if (LightReducer < 0.00 ) LightReducer = 0.05;
if (LightReducer > 2.50 ) LightReducer = 2.50; // May not be larger than 2.55 (value*100 = stored as byte
EEPROM.write(0, (int) (LightReducer * 100)); // Store the value (0-250) in permanent EEPROM memory at address 0
// Serial.print(millis() - RotaryPressTimer); Serial.print(" msec ------- ");
Serial.print(F("LightReducer: ")); Serial.print(LightReducer * 100); Serial.println("%");
}
// --------------------End Light functions
//--------------------------------------------
// CLOCK Input from Bluetooth or Serial
//--------------------------------------------
void ReworkInputString(String InputString)
{
String temp;
float ff;
Serial.println(InputString);
if ( InputString[0] > 64 )
{
int val = InputString[0];
int FMfreq;
switch (val)
{
case 'A':
case 'a':
Toggle_HetWasIsUit = 0; Toggle_HetWasIs = 1; // All tekst displayed
break;
case 'B':
case 'b':
Toggle_HetWasIsUit = 1; Toggle_HetWasIs = 0; // Het Is Was turned off
Serial.println(F("Het Is Was turned off"));
break;
case 'C':
case 'c':
Toggle_HetWasIsUit = 2; Toggle_HetWasIs = 0; // Het Is Was Off after 10 sec
Play_Lights();
break;
case 'D':
case 'd':
Demo = 1 - Demo; // toggle Demo mode
Play_Lights();
GetTijd(0);
Displaytime();
break;
#ifdef FMRADIO
case 'F':
case 'f':
//set FM frequency
temp = InputString.substring(1);
FMfreq = temp.toInt();
if (FMfreq < 8750 ) FMfreq = 8750;
if (FMfreq > 10800) FMfreq = 10800;
RDA5807_setFreq((float) FMfreq/100);
break;
#endif FMRADIO
case 'L': // Lowest value for Brightness
case 'l':
temp = InputString.substring(1);
LowerBrightness = temp.toInt();
if (LowerBrightness < 1 ) LowerBrightness = 1;
if (LowerBrightness > 250) LowerBrightness = 250;
EEPROM.write(1, LowerBrightness); // default Lower Brightness for this clock
break;
case 'M': // factor ( 0 - 1) to multiply brighness (0 - 255) with
case 'm':
temp = InputString.substring(1);
ff = (float)(temp.toInt()) / 100;
WriteLightReducerEeprom(ff);
break;
case 'I':
case 'i':
SWversion();
Display1=255; Display2=255; Display3=255; Laatzien();
Display1=0; Display2=0; Display3=0; Laatzien();
break;
#ifdef FMRADIO
case 'R':
case 'r':
RDA5807_Report();
break;
case 'S':
case 's':
RDA5807_ReadStatus();
break;
case 'T':
case 't':
RDA5807_RDS_Dump();
break;
#endif FMRADIO
default:
break;
}
Displaytime();
#ifdef BLUETOOTHMOD
Bluetooth.print(F( "LightReducer : ")); Bluetooth.print(LightReducer * 100); Bluetooth.println("%");
Bluetooth.print(F( "LowerBrightness: ")); Bluetooth.println(LowerBrightness);
#endif BLUETOOTHMOD
InputString = "";
}
else if (InputString.length() > 3 && InputString.length() <7 )
{
temp = InputString.substring(0,2);
Ihour = temp.toInt();
if (InputString.length() > 3) { temp = InputString.substring(2,4); Iminute = temp.toInt(); }
if (InputString.length() > 5) { temp = InputString.substring(4,6); Isecond = temp.toInt(); }
SetRTCTime();
}
InputString = "";
temp = "";
}
#ifdef FMRADIO
//----------------------------------------- FM radio --------------------------------------------
//--------------------------------------------
// RDA5807 Check if RDS data are available
//--------------------------------------------
void FMradioCheck(void)
{
int uur, minuut, ofs;
if (!Serial.available())
{
RDA5807_ReadW(4); // Read RDS-Data as 4 Word to Array
if ((auRDS[1] & 0xF000) == 0x4000)
{
uur = (16 * (auRDS[2] & 0x0001) + ((auRDS[3] & 0xF000)>>12));
minuut = (auRDS[3] & 0x0FC0)>>6;
ofs = (auRDS[3] & 0x003F);
uur += (ofs / 2);
//Serial.print(F("<"));
}
if (uur<24 && RadioUur != uur && RadioMinuut != minuut) // to avoid a 100 ms delay. Otherwise same time is retrieved many times
{
if (uur < 10) { Serial.print(F(" ")); }
Serial.print(uur); Serial.print(F("u:"));
if (minuut < 10) { Serial.print(F("0")); }
Serial.print(minuut); Serial.println(F("m"));
RadioUur = uur;
RadioMinuut = minuut;
// delay(80);
}
}
}
//--------------------------------------------
// RDA5807 Setup_FMradio
//--------------------------------------------
void Setup_FMradio(void)
{
RDA5807_PowerOn();
RDA5807_Reset();
RDA5807_setFreq(fini);
}
//--------------------------------------------
// RDA5807 Reset Chip to Default Configuration
//--------------------------------------------
int RDA5807_Reset()
{
Serial.println(F("RESET RDA5807"));
for(int i = 0;i < 7; i++) {auRDA5807_Reg[i] = auRDA5807_Regdef[i];}
auRDA5807_Reg[2] = auRDA5807_Reg[2] | 0x0002; // Enable SoftReset
int ret = RDA5807_Write();
auRDA5807_Reg[2] = auRDA5807_Reg[2] & 0xFFFB; // Disable SoftReset
return ret;
}
//----------------------------------------
// RDA5807 Power Off
//----------------------------------------
int RDA5807_PowerOff()
{
RDA5807_setVol(0);
Serial.println("Power OFF RDA5807");
aui_RDA5807_Reg[2]=0x0001; // all bits off
return RDA5807_Write();
auRDA5807_Reg[2] =auRDA5807_Regdef[2]; // Reset to Default Value
}
//----------------------------------------
// RDA5807 Power On
//----------------------------------------
int RDA5807_PowerOn()
{
Serial.println(F("Power ON RDA5807"));
auRDA5807_Reg[3] = auRDA5807_Reg[3] | 0x010; // Enable Tuning
auRDA5807_Reg[2] = auRDA5807_Reg[2] | 0x001; // Enable PowerOn
int ret = RDA5807_Write();
auRDA5807_Reg[3] = auRDA5807_Reg[3] & 0xFFEF; // Disable Tuning
return ret;
}
//----------------------------------------
// RDA5807 Seek up to next Station
//----------------------------------------
int RDA5807_SeekUp()
{
Serial.println(F("SeekUp"));
auRDA5807_Reg[2] = auRDA5807_Reg[2] | 0x0300; // Enable Seekup
RDA5807_Write();
auRDA5807_Reg[2] = auRDA5807_Reg[2] & 0xFCFF; // Disable Seekup
return 0;
}
//----------------------------------------
// RDA5807 Seek down to next Station
//----------------------------------------
int RDA5807_SeekDown()
{
Serial.println(F("SeekDown"));
auRDA5807_Reg[2] = auRDA5807_Reg[2] | 0x0100; // Enable SeekDown(default)
RDA5807_Write();
auRDA5807_Reg[2] = auRDA5807_Reg[2] & 0xFCFF; // Disable Seek
return 0;
}
//----------------------------------------
// RDA5807 Tune Radio to defined Frequency
//----------------------------------------
int RDA5807_setFreq(float mhz)
{
ftun = mhz * 100.0;
Freq_tuned = mhz;
int Chnumber = (int)(( 0.01 + mhz - Freq_lower_bandwith ) / 0.1);
Serial.print(F("Frequency: "));
Serial.print(ftun);
Serial.print(F(" Channel: "));
Serial.println(Chnumber);
Chnumber = Chnumber & 0x03FF;
auRDA5807_Reg[3] = Chnumber * 64 + 0x10; // Channel + TUNE-Bit + Band=00(87-108) + Space=00(100kHz)
Wire.beginTransmission(RDA5807_adrs);
Wire_write16(0xD009);
Wire_write16(auRDA5807_Reg[3]);
Wire.endTransmission();
return 0;
}
//----------------------------------------
// RDA5807 Set Volume
//----------------------------------------
int RDA5807_setVol(int setvol)
{
vol = setvol;
if (vol > 15) {vol = 15; Serial.println(F("Vol already maximal")); return 1; }
if (vol < 0) {vol = 0; Serial.println(F("Vol already minimal")); return 1; }
Serial.print(F("Volume=")); Serial.println(vol);
auRDA5807_Reg[5] = (auRDA5807_Reg[5] & 0xFFF0)| vol; // Set New Volume
RDA5807_WriteReg(5);
return 0;
}
//----------------------------------------
// Write 16Bit To I2C / Two Wire Interface
//----------------------------------------
void Wire_write16(unsigned int val)
{
// if (b_debug) { Serial_print16h(val);}
Wire.write(val >> 8); Wire.write(val & 0xFF);
}
//------------------------------------------
// Serial Print 16Bit Number in HEX as hh:ll
//------------------------------------------
void Serial_print16h(unsigned int uval)
{
byte b_high,b_low;
b_high = uval >> 8; b_low = uval & 0xFF;
if (b_high < 0x10){ Serial.write('0');} Serial.print(b_high,HEX); Serial.write(':');
if (b_low < 0x10){ Serial.write('0');} Serial.print(b_low ,HEX);
}
//----------------------------------------
// RDA5807 Set all Configuration Registers
//----------------------------------------
int RDA5807_Write()
{
Wire.beginTransmission(RDA5807_adrs);
for ( int i = 2; i < 7; i++) { Wire_write16(auRDA5807_Reg[i]);}
return Wire.endTransmission();
}
//----------------------------------------
// RDA5807 Set one Configuration Registers
//----------------------------------------
int RDA5807_WriteReg(int reg)
{
Wire.beginTransmission(RDA5807_adrr);
Wire.write(reg);
Wire_write16(auRDA5807_Reg[reg]);
return Wire.endTransmission();
}
//---------------------------------------------
// RDA5807 Read Special Data Registers as Word
//---------------------------------------------
void RDA5807_ReadW(int cnt)
{
Wire.beginTransmission(RDA5807_adrr); // Device 0x11 for random access
Wire.write(0x0C); // Start at Register 0x0C
Wire.endTransmission(0); // restart condition
Wire.requestFrom(RDA5807_adrr,2*cnt, 1); // Retransmit device address with READ, followed by 8 bytes
for (int i = 0; i < cnt; i++) // Loop for Read data
{auRDS[i] = 256 * Wire.read() + Wire.read();} // Read Data into Array of Unsigned Ints
Wire.endTransmission();
}
//----------------------------------------
// RDA5807 Read and Show all Status Registers
//----------------------------------------
int RDA5807_ReadStatus()
{
int Chnumber = -1;
unsigned int aubuf[8];
memset (aubuf, 0, 8);
Serial.println(F("Info Status RDA5807:"));
Serial.println(F("Reg | 0Ah | 0Bh | 0Ch | 0Dh | 0Eh | 0Fh |"));
Serial.print(F(" |"));
Wire.requestFrom(RDA5807_adrs, 12);
for (int i = 0; i < 6; i++) { aubuf[i] = 256 * Wire.read () + Wire.read(); }
Wire.endTransmission();
for (int i = 0; i < 6; i++) { Serial_print16h(aubuf[i]); Serial.print("|"); }
Serial.println();
Chnumber = (aubuf[0] & 0x03FF);
Freq_tuned = Freq_lower_bandwith + Chnumber * 0.10;
rssi = aubuf[1] >> 10;
Serial.print(F("RDS Data: ")); if ((aubuf[0] & 0x8000)==0){ Serial.println(F("NO"));} else {Serial.println(F("NEW data"));}
Serial.print(F("SEEK Ready: ")); if ((aubuf[0] & 0x4000)==0){ Serial.println(F("no"));} else {Serial.println(F("OK"));}
Serial.print(F("SEEK Fail: ")); if ((aubuf[0] & 0x2000)==0){ Serial.println(F("no, Succces!"));} else {Serial.println(F("FAILED"));}
Serial.print(F("RDS Sync: ")); if ((aubuf[0] & 0x1000)==0){ Serial.println(F("no"));} else {Serial.println(F("OK"));}
Serial.print(F("RDS Block: ")); if ((aubuf[0] & 0x0800)==0){ Serial.println(F("no"));} else {Serial.println(F("Block E"));}
Serial.print(F("Stationmode: ")); if ((aubuf[0] & 0x0400)==0){ Serial.println(F("Mono "));} else {Serial.println(F("Stereo"));}
Serial.print(F("Channel Nr: ")); Serial.print(Chnumber); Serial.print(F(" = "));
Serial.print(Freq_tuned); Serial.println(F(" MHz"));
Serial.print(F("SignalLevel: ")); Serial.println(rssi);
return 0;
}
//----------------------------------------
// RDA5807 Report all available Stations
//----------------------------------------
int RDA5807_Report()
{
Freq_tuned = Freq_lower_bandwith;
int cnt_stations = 0;
int cnt_stereo = 0;
int cnt_rds = 0;
int Rssi = 0;
//auRDA5807_Reg[3] = 0x10; //Set channelnumber 0
//RDA5807_setFreq(87.50);
Serial.println(F("Sender Report:"));
for(int Chnumber = 0; Chnumber <= 210; Chnumber++)
{
auRDA5807_Reg[3] = 64 * Chnumber + 0x10;
Wire.beginTransmission(RDA5807_adrs);
Wire_write16(0xD009);
Wire_write16(auRDA5807_Reg[3]);
Wire.endTransmission();
delay(300); //give de radio some time to settle
RDA5807_Status();
}
}
//----------------------------------------
// RDA5807 Show Status
//----------------------------------------
void RDA5807_Status(void)
{
int Chnumber;
Wire.requestFrom (RDA5807_adrs, 16);
for (int i = 0; i < 8; i++) { auRDA5807_Reg[0x0A + i] = 256 * Wire.read () + Wire.read(); }
Wire.endTransmission();
Chnumber = auRDA5807_Reg[0x0A] & 0x03FF;
rssi = auRDA5807_Reg[0x0B] >> 10;
Freq_tuned = Freq_lower_bandwith + (Chnumber ) * 0.1;
// if ( (auRDA5807_Reg[0x0A] & 0x8000) && (auRDA5807_Reg[0x0A] & 0x0400) ) // if RDS and stereo in station
if ((auRDA5807_Reg[0x0A] & 0x0400) ) // if Stereo in station
{
if (Freq_tuned <= 99.99){Serial.print(" ");}
Serial.print(Freq_tuned);
Serial.print(F(" MHz"));
Serial.print(F(" Ch=")); if (Chnumber < 10){Serial.print(F(" "));} if (Chnumber < 100) { Serial.print(F(" ")); } Serial.print(Chnumber);
Serial.print(F(" PI=")); Serial_printuih(auRDA5807_Reg[0x0C]); // RDS Block A contains Station ID
if ((auRDA5807_Reg[0x0A] & 0x0400) == 0) { Serial.print(F(" Mono "));} else { Serial.print(F(" Stereo"));}
if ((auRDA5807_Reg[0x0A] & 0x8000) == 0) { Serial.print(F(" ---")); } else { Serial.print(F(" RDS")); }
Serial.print(F(" Sig= ")); if (rssi < 10) { Serial.print(F(" ")); } else Serial.print(rssi); Serial.print(F(" "));
for(int i = 0; i < rssi - 5; i++) { Serial.print(F("*")); }
Serial.println();
}
}
//----------------------------------------
// RDA5807 Show Status
//----------------------------------------
void RDA5807_Get_RSSI()
{
Wire.requestFrom (RDA5807_adrs, 16);
for (int i = 0; i < 8; i++) { auRDA5807_Reg[0x0A + i] = 256 * Wire.read () + Wire.read(); }
Wire.endTransmission();
rssi = auRDA5807_Reg[0x0B] >> 10;
}
//----------------------------------------
// SerialPrint 16Bit Number in HEX as hhll
//----------------------------------------
void Serial_printuih(unsigned int val)
{
if (val < 0xF) Serial.print(F("0")); // if less 2 Digit
if (val < 0xFF) Serial.print(F("0")); // if less 3 Digit
if (val < 0xFFF) Serial.print(F("0")); // if less 4 Digit
Serial.print(val,HEX);
Serial.print(F(" "));
}
//----------------------------------------
// RDA5807 Radio Data System Dump Infos
//----------------------------------------
int RDA5807_RDS_Dump()
{
Serial.println(" PI |GTxx|Asci");
while(Serial.available()==0)
{
RDA5807_ReadW(4); // Read RDS-Data as 4 Word to Array
if((auRDS[1] & 0xF000)==0x2000)
{
// Serial_printuih(auRDS[0]); // Block A PI
// Serial_printuih(auRDS[1]); // Block B GT(5Bit)T(1Bit) PTY(5Bit)POS(5)Bit
// Serial_printuih(auRDS[2]);
// Serial_printuih(auRDS[3]);
// int x = 16 + 4*(auRDS[1] & 0x000F);
for (int i=2;i<4;i++)
{
Serial.write(auRDS[i]>>8); // Block C/D Ascii Code
Serial.write(auRDS[i]&0xFF); // 2 * 2 Byte
}
}
if ((auRDS[1] & 0xF000)==0x4000)
{
int i_hh =(16*(auRDS[2] & 0x0001)+((auRDS[3] & 0xF000)>>12));
int i_mm =(auRDS[3] & 0x0FC0)>>6;
int i_ofs=(auRDS[3] & 0x003F);
i_hh=i_hh+(i_ofs/2);
if (i_hh <10){Serial.write(' ');} Serial.print(i_hh); Serial.write(':');
if (i_mm <10){Serial.write('0');} Serial.print(i_mm); Serial.write(' ');
}
if ((auRDS[1]& 0xF000)==0x400)
{
Serial.print(F("RDS CT: ")); for (int i=0;i<4;i++){ Serial_print16h(auRDS[i]); Serial.write(' | ');} Serial.println();
}
delay(80);
Serial.println();
}
return 0;
}
//----------------------------------------
// RDA5807 Radio Data System Dump Infos
//----------------------------------------
int RDA5807_RDS_DumpCT()
{
int i_gt,i_gab,i_pty,i_t,i_pos,i_hh,i_mm,i_ofs;
RDA5807_Status();
Serial.println(F(" PI |GTxx|Asci GT T PTY POS HH:mm Offset"));
while(Serial.available()==0)
{
RDA5807_ReadW(4); // Read RDS-Data as 4 Word to Array
i_gt = auRDS[1] >>12;
if ((auRDS[1] & 0x0800)==0){i_gab='A';} else {i_gab='B';}
i_t =(auRDS[1] & 0x0400)>10;
i_pty=(auRDS[1] & 0x03FF)>>5;
i_pos=(auRDS[1] & 0x000F);
i_hh =(16*(auRDS[2] & 0x0001)+((auRDS[3] & 0xF000)>>12));
i_mm =(auRDS[3] & 0x0FC0)>>6;
i_ofs=(auRDS[3] & 0x003F);
i_hh=i_hh+(i_ofs/2);
if (i_gt==4)
{
Serial_printuih(auRDS[0]); // Block A PI
Serial_printuih(auRDS[1]); // Block B GT(4Bit) A/B(1Bit) T(1Bit) PTY(5Bit)POS(5)Bit
Serial_printuih(auRDS[2]);
Serial_printuih(auRDS[3]);
if (i_gt <10){Serial.write(' ');} Serial.print(i_gt); Serial.write(i_gab); Serial.write(' ');
if (i_t <10){Serial.write(' ');} Serial.print(i_t); Serial.write(' ');
if (i_pty<10){Serial.write(' ');} Serial.print(i_pty); Serial.print(" ");
if (i_pos<10){Serial.write(' ');} Serial.print(i_pos); Serial.write(" ");
if (i_hh <10){Serial.write(' ');} Serial.print(i_hh); Serial.write(':');
if (i_mm <10){Serial.write('0');} Serial.print(i_mm); Serial.write(' ');
Serial.print(i_ofs);
Serial.println();
}
delay(80);
}
return 0;
}
// ------------------ End FM-radio
#endif FMRADIO
//********************************************************************************************