I am using the following code to read power from A0 analog port of an Arduino UNO. The offset value changes from transmitter to transmitter hardware. So it is calibrated once and store in the eeprom. Pin 3 is used to request for change of offset value, but it is called rarely.
The code works, but I finding that the offset value changes after 3-4 days automatically to random value. I am reading only once when the uP starts up. Writing to the EEPROM is done only once for the entire lifetime of the eqpt. I can't fathom why the offset value in the EEPROM changes after 3-4 days?
#include <AltSoftSerial.h> // buffer size 80
#include <EEPROM.h>
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#define Max 23
AltSoftSerial altSerial; // pin(8, 9) (Rx, TX)
char is[50];
char id[]="MAN002";
int data100W = 412;
int offset;
int graph[Max][2] = {
{ 275, 0 }, { 355,5 }, { 366,10 }, { 372,15 }, { 378,20 },
{ 383, 25 }, { 385,30 }, { 389,35 }, { 392,40 }, { 394,45 },
{ 396, 50 }, { 399,55 }, { 401,60 }, { 403,65 }, { 404,70 },
{ 406, 75 }, { 407,80 }, { 408,85 }, { 410,90 }, { 411,95 },
{ 412, 100 }, { 413, 105 }, { 414, 110 }
};
bool ForceSampleReady = false;
bool timerset = true;
char tx_status[3];
char power[4];
char refl[3];
long randNumber;
bool printSerial(char* ch = NULL);
bool printSerialTx(char* * ch = NULL);
bool TimeReadyForTrigger();
void ReadFromTransmitter();
void SyncOrResetGsmAndTx();
void SendSMS();
int predict(float a1, float b1, float a2, float b2, float a3);
bool ForceSampleFlag = false;
bool AdjOffsetFlag = false;
void ForceIntrRoutine()
{
if(!ForceSampleFlag){
ForceSampleFlag = true;
digitalWrite(13, HIGH);
}
}
void AdjOffsetIntrRoutine()
{
if(!AdjOffsetFlag)
{
AdjOffsetFlag = true;
digitalWrite(13, HIGH);
}
}
void setup()
{
attachInterrupt(digitalPinToInterrupt(2), ForceIntrRoutine, CHANGE); // FORCE SAMPLE
attachInterrupt(digitalPinToInterrupt(3), AdjOffsetIntrRoutine, CHANGE); // SET OFFSET
pinMode(A0, INPUT);
pinMode(2,INPUT_PULLUP); // ForceSample
pinMode(3,INPUT_PULLUP); // Adjust 100W offset
pinMode(11,OUTPUT); // GSM Reset pin
digitalWrite(11,LOW); // Pull up reset pin of GSM
pinMode(10, INPUT_PULLUP); // reset offset to 0
pinMode(12, INPUT_PULLUP);
pinMode(A0, INPUT);
analogRead(0);
delay(2000);
pinMode(13,OUTPUT);
digitalWrite(13,HIGH);
Serial.begin(9600);
while (!Serial) ; // wait for serial
Serial.println("");
Serial.println("Transmitter Remote Monitoring");
Serial.println("");
altSerial.begin(9600); //uP to GSM
delay(5000); // wait for altSerial
randomSeed(analogRead(0));
offset = eRead();
Serial.println("\n Offset Value :");
Serial.println(offset);
SyncOrResetGsmAndTx();
Serial.println("Remote Monitoring is listening...");
digitalWrite(13,LOW);
}
int predict(float a1, float b1, float a2, float b2, float a3)
{
float K = (a1 - a3) / (a3 - a2);
float b3 = (K * b2 + b1) / (K + 1.0);
return b3;
}
void eWrite(int val)
{
Serial.println("\nCalling eWrite. ");
byte bytes0 = val >> 8;
byte bytes1 = val & 0xFF;
EEPROM.write(100, bytes0);
delay(500);
EEPROM.write(101, bytes1);
delay(500);
}
int eRead()
{
Serial.println("\nCalling eRead. ");
byte bytes0 = EEPROM.read(100);
delay(500);
byte bytes1 = EEPROM.read(101);
delay(500);
return (bytes0 << 8) + bytes1 ;
}
void SyncOrResetGsmAndTx(){
while(true){
bool result = false;
unsigned long start_time = millis();
while(result == false){
altSerial.println("AT");
delay(3000);
if(printSerial("OK")){
result = true;
Serial.println("Synchronization with GSM modem sucessful.");
altSerial.println("AT+CMGF=1");
delay(3000);
altSerial.println("AT+IPR=9600");
delay(3000);
printSerial();
return;
}
else Serial.println("Failed to synchronize with GSM modem.");
if( millis() - start_time> 6000UL) {
Serial.println("GSM init timeout.");
break;
}
}//while result == false
if( result == false){
// time to reboot gsm
Serial.println("Reset");
digitalWrite(11,HIGH);
delay(300); // Pull down 200ms to LOW
digitalWrite(11,LOW);
delay(6000L); // wait 10 sec for initialization of GSM
// it will retry
}
} //while(true)
}
void loop()
{
delay(100); // reduced from 1 sec
if(TimeReadyForTrigger()){
SyncOrResetGsmAndTx();
int result = -1;
ReadFromTransmitter();
SendSMS();
delay(62000UL); // 1 min plus delay to avoid retriggering
}
if(ForceSampleFlag){
ForceSampleReady = true;
int result = -1;
SyncOrResetGsmAndTx();
ReadFromTransmitter();
SendSMS();
ForceSampleFlag = false;
digitalWrite(13,LOW);
}
if(AdjOffsetFlag)
{
int v = analogRead(0);
//v = map(v,100,470,0,1023);
eWrite(data100W - v );
delay(3000);
digitalWrite(13, LOW);
AdjOffsetFlag = false;
}
if( digitalRead(10) == LOW)
{
eWrite(0);
}
}
void ReadFromTransmitter()
{
long total =0;
int cal_watt;
//int offset = eRead(); // new : offset is read during setup only
for(int j = 0 ; j < 25; j++){
int val = analogRead(0);
val = val + offset;
//Serial.print(val); Serial.print(" ");
if( val<= 350) cal_watt = 0;
else if (val >=440) cal_watt = 110;
else
for (int i = 0; i < Max-1; i++)
{
if (val == graph[i][0])
{
cal_watt = graph[i][1] ;
}
else if (val == graph[i+1][0])
{
cal_watt = graph[i+1][1] ;
}
else if (val >= graph[i][0] && val <= graph[i + 1][0]) {
cal_watt = predict(graph[i][0], graph[i][1], graph[i+1][0], graph[i+1][1], val) ;
}
}
total += cal_watt;
}
cal_watt = int(total/25.0);
Serial.print("offset ");Serial.print(offset);Serial.print(" ");
Serial.print(cal_watt); Serial.println(" watts");
sprintf(power,"%03d",cal_watt);
return ;
}
bool printSerial(char* response)
{
char buffer[120];
int i = 0;
while(altSerial.available()>0 && i<118){
char c = altSerial.read();
buffer[i++] = c;
Serial.print(c); //DEBUG
}
buffer[i++] = '\0';
if(response != NULL){
char* p = NULL;
p = strstr(buffer, response);
if( p!= NULL) return true;
}
return false;
}
void SendSMS(){
tmElements_t tm;
//digitalWrite(13,LOW);
//delay(1000);
//digitalWrite(13,HIGH);
RTC.read(tm);
delay(3000);
char end[2];
end[0]=0x1a;
end[1]='\0';
char sms[120];
strcpy(tx_status,"ON");
strcpy(refl,"0");
//sprintf(sms,"ID=%s$Tx=%s$Power=%s$Refl=%s$Date=%02d/%02d/%04d$Time=%02d:%02d:%02d$", id, (!FlagTxResponding?"NA" : tx_status?"ON":"OFF"), power, refl, tm.Day, tm.Month, tmYearToCalendar(tm.Year), tm.Hour, tm.Minute, tm.Second);
//"StnID=E732323&Date=07/06/2020&Time=14:49:26&Power=70&Refl=1&Status=ON"
sprintf(sms,"StnID=%s&Date=%02d/%02d/%04d&Time=%02d:%02d:%02d&Power=%s&Refl=%s&Status=%s",
id,
tm.Day, tm.Month, tmYearToCalendar(tm.Year),
tm.Hour, tm.Minute, tm.Second,
power,
refl,
tx_status
);
//Serial.println(sms);
// this may take upto 15sec if GSM resets or it may be in indefinite loop
for(int repeats = 0; repeats < 1; repeats++){
altSerial.println("AT+CMGS=\"+446033800000\"");
delay(3000);
if(printSerial(">")) { Serial.println("Ready for SMS"); } else { Serial.println("Not ready for SMS"); continue;}
//altSerial.print(sms);
for(int i=0;i<strlen(sms);i++){
altSerial.print(sms[i]);
delay(10);
}
altSerial.write(0x1A); //println((char)26);
bool time_out = false;
unsigned long start_time = millis();
while (!printSerial("OK"))
{
//Serial.print("@");
delay(1000UL);
if( millis() - start_time > 20000UL) {
//Serial.println("GSM init timeout.");
time_out = true;
break;
}
}
if( !time_out) { Serial.println("SMS Sent"); break; } else { Serial.println("SMS not sent"); continue;}
} //for
}
bool TimeReadyForTrigger(){
tmElements_t tm;
RTC.read(tm);
delay(3000);
int t[] = {6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21};
//static bool first_time = true;
//static int last_hr = -1;
//Serial.println(tm.Minute);
for(int i =0; i< 16; i++){
if(tm.Hour == t[i] && tm.Minute == 0 ){ //&& tm.Hour != last_hr){
//Serial.println("Time trigger");
//first_time = false;
//last_hr = tm.Hour;
return true;
}
}
return false;
}