I am helping my daughter figure out a problem with her Arduino project. She has an analog input that is controlled via a relay. The coil for the relay requires about 20mA @ 5V. This is pushing the limits for a port pin I believe.
Anyway the analog reading is from a couple of resistors hooked in a divider. The divider is only for testing but it's rock solid and does include a 0.1uF cap across the A0 input to gnd. I didn't pull out the scope but it appears to be fine.
So here is the problem. When she is reading the analog pin and displaying it on the serial terminal it's nice and steady. As soon as she energizes the relay the analog value drops down as it should (her signal is being loaded when the relay is on) and for about one minute (sampling once a second) the returned values look solid - not moving around.
After a minute or so the analog values being printed over the terminal start to fluctuate by 100mV or so. So now I am wondering is it the combination of the relay taxing the port pin plus the floating point math that may be causing the processor to churn away and it self heats?
Anyone notice if the ADC fluctuates like this when or if it is heated?
If it's not a thermal issue perhaps it's accumulated error in the math? She declared the float variable as volatile so I doubt there is any residual values that accumulate and causes the calculation to be off after a number of iterations?
Are you powering the relay from the arduino board with external voltage? In that case check the temperature of the voltage regulator chip located next to the barrel connector towards the usb connector. If you are powering the arduino board from usb the issue can be here. I have experienced problems with usb voltages dropping down to 4V
Can you please post a copy of your sketch, using code tags.
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf?
A current of 20mA is not pushing the arduino pin's capacity at all but are you sure that it is right. It seems very low for a relay, do you have a relay board?
It could be your wiring, make sure you use a star wiring for the grounds. If you don't know what that is then just use a different ground on the arduino for relay coil and measuring resistor.
Proto shield used. I can try to put together a quick schematic but it's honestly fairly simple. A relay fires to engage a 1K ohm resistor to ground. The source node is at the moment a resistor divider to provide about 2.5V prior to the relay firing and about 0.5V after it fires. The coil for the relay is specified at 35 ohms nominal (at least on the package it says that).
Updated the actual relay used above. I see it's rated for as much as 90mA coil current! I think I found the problem!
The code is not difficult. A snippet is attached:
// Variable for the measured data - seconds since test started
volatile int time = 0;
// Initialize analog use variables
volatile int voltSense = 0; // Variable for the voltage reading
volatile float voltage = 0; // Voltage measured (calculated)
--SNIP--
// Check if voltage is > 0.1V
while (voltSense >= 20) {
time = ++time;
lcd.setCursor(8, 1);
// Write to the LCD for display
lcd.print(voltage, 4);
// Log the data through the serial port
Serial.print(time);
Serial.print(", ");
Serial.println(voltage, 4);
// Wait one second and read it again
delay (1000);
voltSense = analogRead(A0);
voltage = voltSense * (5.0 / 1023.0);
}
--SNIP--
The proto shield is not allowing me to see if the regulator is overheating. I will try later today to see if this is the case.
Will recommend she change the drive for the coil to a PMOS transistor to reduce the load on the micro pin. Will also check the regulator. I noticed she has a stepper motor (off for the measurements) but two of the LED's on the driver board were still lit. It may be using extra power there as well.
Made sure stepper was off completely and verified the coil current was not terrible. Readings are much more consistent (within 1 LSB). Think her regulator was overheating and that caused the readings to go all out of whack. Will have to go over the details with her so she understands what occurred.
Didn't help things using a 12V wall wart supply. The regulator has to dissipate a lot of power using 12V VIN. I'll see if we have a spare 7-9V one lying around.
Can you expand on that a bit. I was under the assumption that volatile informed the compiler to never optimize that value and keep it as a memory element that must be read each time fresh. What is a good alternative? Just the float and nothing more?
I was thinking she could post process the logged data and only worry about the integer values. Would certainly speed things up and likely reduce power a bit more.
That is what it does, but why do you want to do that? The reason it is there is so that if something changes the memory location without the compiler's knowledge (An interrupt, for example) the compiler will always access the memory. If you have nothing going on that will change that memory location, there is no reason for volatile, and if the compiler wants to keep it in a register, it can't.