Issue with powering relay and several sensors with Arduino

Hello,

I am working on solar panel station that can change the solar panel tilt angle during the day to collect the output power related to each tilt angle.

I am using actuator 12V 2A. , and controlling the actuator by two relays and Arduino for going up and down.

I am using different sensors to measure voltage, current, compass orientation, panel surface temperature as well as Nextion screen and HC-12 module to transmit the data.

I am powering the system with a Gel battery 150AH with MPPT battery charger controller. I am using two Lm2596 buck converters to supply 5V, one for Arduino and other accessories, and the other one for relay separately.

The problem is: When I turn on the actuator by relay, Arduino seems to be frozen that cannot control anything until I press the reset button, and then the system back on. I read several topics about decoupling and bypass capacitors that can solve the problem, but it did not work. I added two 10uF capacitors along the 5V and Gnd of Arduino. Gnd of the two buck converters are connected to be a common Gnd.

I will add a picture of the setup I am using to make it clear to the reader.

Here is the code I am using and thank you.

/*..........Nextion screen library..............*/
#include "EasyNextionLibrary.h"  // Include EasyNextionLibrary
EasyNex myNex(Serial);
/*..........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];
byte Temperature = 0;
/*...........Controlling actuator variables................*/ 
byte act_Up = 3;
byte act_Down = 2; 
byte button_Up = 8;
byte button_Down = 9;
/*.........Voltage reading variables..................*/
float Volt;
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.00;
const double resConvert = 1024;
double resADC = vRef/resConvert;
double zeroPoint = vRef/2;
#define NUMSAMPLES_c 20
float samples_c[NUMSAMPLES_c];
/*............Compass sensor QMC5883 variables.............*/
#include <Wire.h>
#include <DFRobot_QMC5883.h>
DFRobot_QMC5883 compass;
int Orientation = 1; 
/*............. HC-12 communication....................*/ 
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
int data[3] = {0, 0, 0};
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
const unsigned long Interval = 5000;

void setup() {
  myNex.begin(9600);
  Serial.begin(9600);
  HC12.begin(9600);
  while (!compass.begin())
  {
    Serial.println("Could not find a valid QMC5883 sensor, check wiring!");
    delay(500);
  }

    if(compass.isHMC()){
        Serial.println("Initialize HMC5883");
        compass.setRange(HMC5883L_RANGE_1_3GA);
        compass.setMeasurementMode(HMC5883L_CONTINOUS);
        compass.setDataRate(HMC5883L_DATARATE_15HZ);
        compass.setSamples(HMC5883L_SAMPLES_8);
    }
   else if(compass.isQMC()){
        Serial.println("Initialize QMC5883");
        compass.setRange(QMC5883_RANGE_2GA);
        compass.setMeasurementMode(QMC5883_CONTINOUS); 
        compass.setDataRate(QMC5883_DATARATE_50HZ);
        compass.setSamples(QMC5883_SAMPLES_8);
   }
  pinMode(button_Up,INPUT_PULLUP);
  pinMode(button_Down,INPUT_PULLUP);
  pinMode(act_Up,OUTPUT);
  pinMode(act_Down,OUTPUT);
  digitalWrite(act_Up,HIGH);
  digitalWrite(act_Down,HIGH);
}

void loop() {
  myNex.NextionListen();
  Vector norm = compass.readNormalize();
  // Calculate heading
  float heading = atan2(norm.YAxis, norm.XAxis);
  float declinationAngle = (3.0 + (43.0 / 60.0)) / (180 / PI); //for Jeddah 3.43E (positive)
  heading += declinationAngle;
  // Correct for heading < 0deg and heading > 360deg
  if (heading < 0){
    heading += 2 * PI;
  }
  if (heading > 2 * PI){
    heading -= 2 * PI;
  }
  float headingDegrees = heading * 180/M_PI;

  if (headingDegrees> 110 && headingDegrees <190){
    Orientation = '1'; // 1 for south
  }
  else if (headingDegrees> 200 && headingDegrees <260){
    Orientation = '2'; // 2 for West
  }
  else if (headingDegrees> 270 && headingDegrees <340){
    Orientation = '3';  //3 for North
  }
  else {Orientation = '4';} //4 for East 
  
  ReadingA1 = analogRead(A0);
  Volt = ReadingA1 * (5.0/1024)*((R1 + R2)/R2);    

  for (int i=0; i< NUMSAMPLES_c; i++) {
      Vout = resADC * analogRead(A1);   
      Current = (zeroPoint - Vout)/ scale_factor;
      samples_c[i] = Current;
      delay(50);}
    // average all the samples out
  float average_c = 0.0;
  for (int i=0; i< NUMSAMPLES_c; i++) {
       average_c += samples_c[i];}   
    average_c /= NUMSAMPLES_c;

  float calibratedCurrent = (1.1516*average_c)-0.0484;
  
  Temperature = readTemp(2);
  int power = Volt*average_c;
 
   /*myNex.writeNum("n0.val", Temperature);
   if(Orientation == 1){myNex.writeStr("t4.txt","S");}
   else if (Orientation == 2){myNex.writeStr("t4.txt","W");}
   else if (Orientation == 3){myNex.writeStr("t4.txt","N");}
   else if (Orientation == 4){myNex.writeStr("t4.txt","E");}
   myNex.writeNum("n1.val", power);
   myNex.writeNum("j0.val", power);*/

  currentMillis = millis();
  if(currentMillis-previousMillis>Interval){
  Serial.print("Volt: ");
  Serial.println(Volt);
  Serial.print("Current: ");
  Serial.println(average_c);
  Serial.print("Calibrated Current: ");
  Serial.println(calibratedCurrent);
  Serial.print("Temperature: ");
  Serial.println(Temperature);
  Serial.print("Compass degree: ");
  Serial.println(headingDegrees);

  for(int i=0;i++;i<3){
    if(i == 0){data[i]=power;}
    else if (i == 1){data[i]=Temperature;}
    else if (i ==2){data[i]=Orientation;}
  }
  
  String dataString = "";
  for (int i = 0; i < 3; i++) {
    dataString += String(data[i]);
    if (i < 2) {
      dataString += ",";
    }
  }
  HC12.println(dataString);
  previousMillis = currentMillis; 
  }
  

  if(digitalRead(button_Up)==LOW){
    digitalWrite(act_Up,LOW);
  }
  else{digitalWrite(act_Up,HIGH);}

  if(digitalRead(button_Down)==LOW){
    digitalWrite(act_Down,LOW);
  }
  else{digitalWrite(act_Down,HIGH);}
}


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;
}

A schematic will also be required for coherent communication. A Fritzing diagram, properly completed and annotated, might suffice, but if it's as bad as typical Fritzing efforts, it'll get you a lot of flak. Nothing beats a good, clear, complete schematic.

I tried to make it clear as much as possible.

It is better to power the Arduino through the VIN pin. You can supply voltage via the 5V pin, however this bypasses the regulator, and can damage your board.

I previously used the the vin pin with 9-12 Volts with other projects, but the linear regulator got very hot in many times.

SO you suggest supplying 12V through Vin pin.

9 volts is best.

Powering the Uno with 5volt is fine.

I don't see any back-emf diodes across the relay contacts.
No diodes there will likely lock up the Arduino when the motors turn off.
Use a bridge rectifier. AC pins to the motor, + and - to the supply.

A mosfet H-bridge motor driver instead of the relays could be an improvement.
Then only one buck converter will be needed. And no diode problem.
Leo..

@Wawa, I just used H-bridge motor driver (IBT-2) instead of relay, and the problem stays the same.

When I upload a simple sketch to drive the motor up and down, it works fine without any problem, but when I used the whole system code as shown above, the actuator moves up and down one or two times, then the system frozen again! :smiling_face_with_tear:

I am trying to figure out any problem in the code, but nothing shows up.

Can't help you with code.
All I can say is that you normally build up code and hardware in small steps, and test after each addition. Only then you will know which part is creating problems.
Fault finding afterwards is much harder. Serial.prints in stategic places could help you.

I think you should tidy up your wiring too. A spider like that, with power wiring and signal wiring close to each other can't be good.
And what voltage sensor are you using. Many MPPT controllers regulate the negative wire of the solar panel, resulting in a negative voltage on the negative wire of the panel.
Leo..

So, looked over everything fairly closely, can't see anything obviously wrong. Could be something up with using hardware serial and two software serials, a LOT of possible interrupts there, think I tried using two software serials on a tiny85 at one point and it just didn't work for some reason. So you could try commenting out those and see how it performs.
Also doesn't seem like there's much memory usage but still use of a "String" data form... could be fine but have had as many problems with them as i have floating point math requiring < > not = at all times. Usually better to have an array of chars (in my opinion).
Have you checked your voltage rails while turning on/off the relays? Multimeter might catch a nasty voltage spike if it happens at the right time? If so, an inline low value (10-200ohm) resistor on the data side positive supply rail might help reduce their current consumption and stabilize things.
Lastly, are the 5v and 12v grounds separate? If so could cause issues at the relay board. Also does the relay board pull its inputs high already and only activate when pulled low, if so what kind of current is the arduino pulling when it is pulled low? Also back emf is an issue, but would HOPE the board your using has protection diodes built in, although no way of testing if they still work without removing them unfortunately.

Oh and supplying the arduino with 5v is fine, for 16mhz as long as its between like ~4v and below 6v it should operate perfectly fine. Lol just had to add this from arduino - "Overclocking" an AVR - Electrical Engineering Stack Exchange


Am watching the post but not often active here so might not reply.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.