Hello everyone,
I am working on a solar panel system that change its tilt angle 5 times every 15 minutes starting at 6:30 am and end at 6:00 pm. The system uses RTC, SD card module, HC-12 module, Nextion screen, temperature, voltage, and current sensors with Arduino Mega.
The system communicates with another Arduino Uno that control the actuator of solar panel based on encoder sensor to determine the angle via I2C.
So the first Arduino Mega is the master, and Arduino Uno is the slave that rotate the panel when the Arduino Mega send a signal.
The problem with the system is that it works correctly for half an hour, sometime for one hour. Then the Arduino Uno stops rotate the actuator, or sometimes the angle is change correctly, but the actuator does not move.
I will attach the cirecuit diagram, the code for master and slave in the following:
Circuit schematic:
Arduino Mega code (MASTER):
/*..........Nextion screen library..............*/
#include "EasyNextionLibrary.h" // Include EasyNextionLibrary
EasyNex myNex(Serial2);
/*..........Reading panel temperature variables......*/
#define THERMISTORNOMINAL 10000 // temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25 // how many samples to take and average, more takes longer
#define NUMSAMPLES 5// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT -3950// the value of the 'other' resistor
#define SERIESRESISTOR 10000
int samples[NUMSAMPLES];
int Temperature = 0;
/*.........Voltage reading variables..................*/
float Volt;
float CalibratedVolt;
float R1 = 30000.0;
float R2 = 7500.0;
int ReadingA1 = 0;
/*.........Current reading variables..................*/
double Vout = 0;
double Current = 0;
const double scale_factor = 0.066; // 30A
const double vRef = 5.1;
const double resConvert = 1024;
double resADC = vRef/resConvert;
double zeroPoint = vRef/2;
#define NUMSAMPLES_c 20
float samples_c[NUMSAMPLES_c];
/*............. HC-12 communication....................*/
int data[3] = {0, 0, 0}; //{Power, Temperature, Degree}
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
const unsigned long Interval = 5000;
int power = 0;
byte degree = 32;
/*..............RTC module...........................*/
#include "RTClib.h"
#include <Wire.h>
RTC_DS3231 rtc;
int Hour;
int Min;
int Day;
int Month;
int Year;
bool MotorLock = false;
bool System = true;
unsigned long TIMER = 0;
const unsigned long Interval_1 = 2000;
/*..............SD card reader....................*/
#include <SPI.h> //SPI Comms for SD Card reader
#include <SD.h> //SD Card reader
const int chipSelect = 53;
void setup() {
Wire.begin();
myNex.begin(9600); //for screen
delay(50);
Serial.begin(9600); //for PC
delay(50);
Serial1.begin(9600); // for HC-12
delay(50);
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
while (1);
}
Serial.println("card initialized.");
if (! rtc.begin()){
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
if (rtc.lostPower()) {
Serial.println("RTC is NOT running, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// 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(2023, 9, 24, 16, 39, 0));
}
//rtc.adjust(DateTime(2023, 10, 2, 1, 29, 0));
}
void loop() {
myNex.NextionListen();
DateTime now = rtc.now();
Hour = now.hour();
Min = now.minute();
Day = now.day();
Month = now.month();
Year = now.year();
if(Hour == 6 && Min == 30){System = true;}
else if (Hour == 18 && Min == 0){System = false;}
ReadingA1 = analogRead(A0);
Volt = ReadingA1 * (5.0/1024)*((R1 + R2)/R2); // 0-1024 25
CalibratedVolt = (1.226*(Volt+1.8))-4.5442;
if(CalibratedVolt < 0.5){CalibratedVolt = 0.0;}
for (int i=0; i< NUMSAMPLES_c; i++) {
Vout = resADC * analogRead(A1);
Current = (zeroPoint - Vout)/ scale_factor;
samples_c[i] = Current;
delay(20);}
double average_c = 0.0;
for (int i=0; i< NUMSAMPLES_c; i++) {
average_c += samples_c[i];}
average_c /= NUMSAMPLES_c;
double calibratedCurrent = 2.358*log(average_c)+1.4262;
if(calibratedCurrent < 0.5){calibratedCurrent = 0.0;}
Temperature = readTemp(2);
power = CalibratedVolt*calibratedCurrent;
if(millis()-TIMER>Interval_1){
Wire.requestFrom(8, 1);
while (Wire.available()){
degree = Wire.read();}
myNex.writeNum("n0.val", Temperature);
myNex.writeNum("n2.val", Hour);
myNex.writeNum("n3.val", Min);
myNex.writeNum("n4.val", Day);
myNex.writeNum("n5.val", Month);
myNex.writeNum("n6.val", Year);
myNex.writeNum("n7.val", degree);
myNex.writeNum("n1.val", power);
myNex.writeNum("j0.val", power);
delay(50);
Serial.print("Motor Lock:");
Serial.println(MotorLock);
Serial.print("System:");
Serial.println(System);
TIMER = millis();}
if(System == true){
if(Min == 0 || Min == 15 || Min == 30 || Min == 45){
if(MotorLock == false){
Wire.beginTransmission(8);
Wire.write(1);
Wire.endTransmission();
MotorLock = true;}
}
else if(Min == 55 || Min == 10 || Min == 25 || Min == 40){
MotorLock = false;
}
currentMillis = millis();
if(currentMillis-previousMillis>Interval){ //5000 = 5 seconds
for(int i=0;i<3;i++){ //data[3] = {power: 50,Temp: 45,Degree: 27}
if(i == 0){data[i]=power;}
else if (i == 1){data[i]=Temperature;}
else if (i ==2){data[i]=degree;}
}
String dataString = ""; // dataString = "50,45,27,1"
for (int i = 0; i < 3; i++) {
dataString += String(data[i]);
if (i < 2) {
dataString += ",";
}
}
Serial1.println(dataString); //Sent by HC-12
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.print(now.year(), DEC);
dataFile.print('/');
dataFile.print(now.month(), DEC);
dataFile.print('/');
dataFile.print(now.day(), DEC);
dataFile.print(',');
dataFile.print(now.hour(), DEC);
dataFile.print(':');
dataFile.print(now.minute(), DEC);
dataFile.print(':');
dataFile.print(now.second(), DEC);
dataFile.print(",");
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
previousMillis = currentMillis; // 60000 65500
}
}
}
float readTemp(int pin){
uint8_t i;
float average;
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(pin);
delay(10);}
// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];}
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart = 0.0;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert absolute temp to C
return steinhart;
}
Arduino Uno code (SLAVE):
#include <Arduino.h>
#include <Wire.h>
int encoder_Pin_1 = 2;
int encoder_Pin_2 = 3;
int up = 6;
int down = 7;
byte degree = 32;
volatile int lastEncoded = 0;
volatile long encoderValue;
long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
int stage = 0;
bool System = false;
bool lock = false;
unsigned long currentMillis = 0;
unsigned long PreviousMillis = 0;
const unsigned long Interval = 30000;
void setup(){
Serial.begin(9600);
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
Wire.onReceive(receiveEvent); // register event
pinMode(up,OUTPUT);
pinMode(down,OUTPUT);
pinMode(encoder_Pin_1, INPUT);
pinMode(encoder_Pin_2, INPUT);
digitalWrite(encoder_Pin_1, HIGH); //turn pullup resistor on
digitalWrite(encoder_Pin_2, HIGH); //turn pullup resistor on
//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
digitalWrite(up,LOW);
digitalWrite(down,HIGH);
delay(10000);
digitalWrite(up,HIGH);
delay(1000);
}
void loop(){
Serial.print("System: ");
Serial.println(System);
Serial.print("degree: ");
Serial.println(degree);
if(System == true){
if(encoderValue >= 1 && stage == 0){
digitalWrite(down,HIGH);
degree = 27;
if(lock == false){
currentMillis = millis();
PreviousMillis = currentMillis;
lock = true;}
currentMillis = millis();
if(currentMillis - PreviousMillis > Interval){
stage = 1;
digitalWrite(down,LOW);
lock = false;}
}
else if(encoderValue >= 16 && stage == 1){
digitalWrite(down,HIGH);
degree = 22;
if(lock == false){
currentMillis = millis();
PreviousMillis = currentMillis;
lock = true;}
currentMillis = millis();
if(currentMillis - PreviousMillis > Interval){
digitalWrite(down,LOW);
lock = false;
stage = 2;}
}
else if(encoderValue >= 30 && stage == 2){
digitalWrite(down,HIGH); //stage 2 == 17 degrees
degree = 17;
if(lock == false){
currentMillis = millis();
PreviousMillis = currentMillis;
lock = true;}
currentMillis = millis();
if(currentMillis - PreviousMillis > Interval){
digitalWrite(down,LOW);
lock = false;
stage = 3;
}
}
else if(encoderValue >= 47 && stage == 3){
digitalWrite(down,HIGH); //stage 3 == 12 degrees
degree = 12;
if(lock == false){
currentMillis = millis();
PreviousMillis = currentMillis;
lock = true;}
currentMillis = millis();
if(currentMillis - PreviousMillis > Interval){
digitalWrite(up,LOW);
lock = false;
stage = 4;}
}
else if(encoderValue == 0 && stage == 4){
digitalWrite(up,HIGH);
degree = 32;
if(lock == false){
currentMillis = millis();
PreviousMillis = currentMillis;
lock = true;}
currentMillis = millis();
if(currentMillis - PreviousMillis > Interval){
lock = false;
System = false;}
}
}
}
void receiveEvent() {
byte x;
while (0 < Wire.available()) {
x = Wire.read();
}
digitalWrite(down,LOW);
System = true;
stage = 0;
delay(50);
}
// function that executes whenever data is requested by master
void requestEvent() {
Wire.write(degree); // respond with message of 1 byte
}
void updateEncoder()
{
int MSB = digitalRead(encoder_Pin_1); //MSB = most significant bit
int LSB = digitalRead(encoder_Pin_2); //LSB = least significant bit
int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
lastEncoded = encoded; //store this value for next time
}
Could anyone see any mistake with my work here, because I changed the coding several times, and check the hardware million times as well
.

