Relays getting freeze suddenly - arduino-uno

Hi all, I'v done a project for a factory which were needing a packing machine, so I made it with some pneumatic cylinders using arduino, relays, IR sensor.
I'm attaching my code and a picture how schema looks because sometimes my relays are freezing suddenly and they just need to power off then again power on and its OK.
Btw; I'm attaching schema only for one relay with all elements, code is for 4
relays.
Any idea about this please?
Picture of schema
int relay1 = 13;
int relay2 = 12;
int relay3 = 11;
int relay4 = 10;
int sensor1 = 5;
int sensor2 = 6;
int sensor3 = 3;
int sensor4 = 2;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(relay1, OUTPUT);
pinMode(sensor1, INPUT);
pinMode(relay2, OUTPUT);
pinMode(sensor2,INPUT);
pinMode(relay 3, OUTPUT);
pinMode(sensor3,INPUT);
pinMode(relay4, OUTPUT);
pinMode(sensor4,INPUT);
pinMode(LED_BUILTIN,OUTPUT);
}
void loop() {
digitalWrite(relay1, LOW);
delay(2000);
digitalWrite(relay1, HIGH);
delay(2000);
digitalWrite(relay2, LOW);
delay(2000);
digitalWrite(relay2, HIGH);
delay(2000);
digitalWrite(relay 3, LOW);
delay(2000);
digitalWrite(relay3, HIGH);
delay(2000);
digitalWrite(relay4, LOW);
delay(2000);
digitalWrite(relay4, HIGH);
delay(2000);
while(1){
delay(100);
if(digitalRead(sensor2) == LOW)
{
Serial.println("Eggs on");
digitalWrite(relay1,HIGH);
delay(350); // shpejtesia sensorit // sensor speed
}
else
{
Serial.println("No eggs");
digitalWrite(relay1,LOW);
delay(50); // sa mu kthy shpejt klipi mbrapa // speed of cylinder getting back
}
if(digitalRead(sensor1) == LOW)
{
Serial.println("Eggs on");
digitalWrite(relay2,HIGH);
delay(350); // shpejtesia sensorit // sensor speed
}
else
{
Serial.println("No eggs");
digitalWrite(relay2,LOW);
delay(50); // sa mu kthy shpejt klipi mbrapa // speed of cylinder getting back
}
if(digitalRead(sensor3) == LOW)
{
Serial.println("Eggs on");
digitalWrite(relay3,HIGH);
delay(350); // shpejtesia sensorit // sensor speed
}
else
{
Serial.println("No egs");
digitalWrite(relay3 ,LOW);
delay(50); // sa mu kthy shpejt klipi mbrapa // speed of cylinder getting back
}
if(digitalRead(sensor4) == LOW)
{
Serial.println("Eggs on");
digitalWrite(relay4,HIGH);
delay(100); // shpejtesia sensorit // sensor speed
}
else
{
Serial.println("No eggs");
digitalWrite(relay4 ,LOW);
delay(50); // sa mu kthy shpejt klipi mbrapa // speed of cylinder getting back
}
}

I design systems with relays operating in production plants. Sticking of the relays is a rare condition, but can occur in certain situations.
Relay Coil Voltage Stability ----
If the relay coil voltage is insufficient then the relays may fail to switch on. I would measure the voltage at coil switch on ensure that the relay coil voltage is stable. For best results I would supply the relay coils from a separately regulated (5 VDC) supply. That ensures that any loading affects of the relay coils on the supply voltage do not cause dropouts on the Arduino supply and stop the program.
Relay Contact Erosion due to inductive loads ----
Relay contacts can become eroded over time, occasionally sticking and eventually welding shut. The damage occurs when switching inductive loads off. The inductive load's energy discharges across the contacts and can generate an arc in the contact gap if the inductively generated voltage is sufficiently high. The plasma then erodes the contacts. A solution is to add a transorb across the contacts that is rated above the normal load voltage (e.g. above 24 VDC). This will absorb the inductive energy harmlessly. Another option is an RC filter. See the relay manufacturer's technical guidelines for more information on this subject.
Some issues that may be present in you system. The details are not apparent from the posted circuit diagram due to absence of some of the circuitry.
Isolation of Earths ----
Ensure that the earth voltages of the Arduino and 24V power are not connected. Otherwise there may be an Arduino earth voltage spike when you are swuitching on and off the solenoids. This could trip of the Arduino and halt the program. The Arduino power and the 24 VDC power sources should be independent and floating.
Relay Driver Isolation ----
Add optical isolators to the relay driver circuit so that there is at least a 1000 V barrier between the Arduino and the relay driver.
Relay Coil Voltage Suppression ----
Add a reverse polarity diode connected across the coil to absorb the inductive energy when the relay coil discharges. Otherwise that energy may cause damage to the arduino output pin.
Good luck with your system

Related

calculating wind speed from frequency value

I have NRG #40 wind speed sensor the output frequency is linear with wind speed
output signal range from 0 Hz to 125 Hz
0 Hz mean =0.35 m/s and 125 Hz =96 m/s and transfer function is
m/s = (Hz x 0.765) + 0.35
How can I interface this sensor with a Arduino mega
previously I connect Adafruit (product ID: 1733) which is output voltage not frequency is linear with wind speed
and this code for Adafruit :
//Setup Variables
const int sensorPin = A0; //Defines the pin that the anemometer output is connected to
int sensorValue = 0; //Variable stores the value direct from the analog pin
float sensorVoltage = 0; //Variable that stores the voltage (in Volts) from the anemometer being sent to the analog pin
float windSpeed = 0; // Wind speed in meters per second (m/s)
float voltageConversionConstant = .004882814; //This constant maps the value provided from the analog read function, which ranges from 0 to 1023, to actual voltage, which ranges from 0V to 5V
int sensorDelay = 1000; //Delay between sensor readings, measured in milliseconds (ms)
//Anemometer Technical Variables
//The following variables correspond to the anemometer sold by Adafruit, but could be modified to fit other anemometers.
float voltageMin = .4; // Mininum output voltage from anemometer in mV.
float windSpeedMin = 0; // Wind speed in meters/sec corresponding to minimum voltage
float voltageMax = 2.0; // Maximum output voltage from anemometer in mV.
float windSpeedMax = 32; // Wind speed in meters/sec corresponding to maximum voltage
void setup()
{
Serial.begin(9600); //Start the serial connection
}
void loop()
{
sensorValue = analogRead(sensorPin); //Get a value between 0 and 1023 from the analog pin connected to the anemometer
sensorVoltage = sensorValue * voltageConversionConstant; //Convert sensor value to actual voltage
//Convert voltage value to wind speed using range of max and min voltages and wind speed for the anemometer
if (sensorVoltage <= voltageMin){
windSpeed = 0; //Check if voltage is below minimum value. If so, set wind speed to zero.
}else {
windSpeed = (sensorVoltage - voltageMin)*windSpeedMax/(voltageMax - voltageMin); //For voltages above minimum value, use the linear relationship to calculate wind speed.
}
//Print voltage and windspeed to serial
Serial.print("Voltage: ");
Serial.print(sensorVoltage);
Serial.print("\t");
Serial.print("Wind speed: ");
Serial.println(windSpeed);
delay(sensorDelay);
}
Asuming you use a Arduino UNO or Nano, a easy way is to connect the sensor to pin D2 or D3, witch can be used as Interrupt pins.
You then make a function, or a ISR, that gets called every time the sensor pulses. Then you attach the newly created function to the Interrupt pin.
So it will look something like this.
byte sensorPin = 2;
double pulses = 0;
double wSpeed = 0;
long updateTimer = 0;
int updateDuration = 3000;
void setup() {
Serial.begin(115200);
pinMode(sensorPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(sensorPin), sensorISR, FALLING);
}
void loop() {
long now = millis();
if(updateTimer < now) {
updateTimer = now + updateDuration;
wSpeed = ((pulses/(updateDuration/1000)) * 0.765) + 0.35;
pulses = 0;
Serial.println("Windspeed is:" + String(wSpeed));
}
}
void sensorISR() {
pulses++;
}
The ISR functions only job is to increment the pulses variable for every pulse. Then every second you can calculate the frequency and speed. If you wait 3 second instead, like above, you will have a better resolution but will have to account for the extra time in the equation.
I have not testet this code.

Controlling the brigthness of LED using Arduino

I wrote a sample code to measure the brightness of LED by controlling the duty cycle of LED connected to Arduino. I want to get the range of least bright light to max bright light for a specific period of period. When i put desired_brightness = 1, the LED is emitting light at 93 lux units, its not the least brightlight. Any suggestion on how to get the least bright light?
int led = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int incrementfactor = 10; // how many points to fade the LED by
int desired_brightness = 255 ;
int extra_delay = 1000;
void setup() { // declare pin 9 to be an output:
pinMode(led, OUTPUT);
analogWrite(led, desired_brightness);
}
void loop() {
analogWrite(led, desired_brightness);
brightness=brightness+incrementfactor;
if (brightness==desired_brightness) {
delay(extra_delay);
}
}
I've tailored your code a bit. The main problem was you were going to maximum brightness right away, and were never decreasing it. analogWrite() only takes values from 0 to 255. You were starting at 255 and increasing from there, so it just stayed bright. Try this instead, it's the "breathing effect" you see on so many electronics these days, and loops forever:
int ledPin = 3; // the pin that the LED is attached to
int brightness =0; // how bright the LED is
int extra_delay = 1000; // the extra delay at max
int super_delay = 5000; // super delay at min
int direction = 1; // the dimmer-brighter direction
void setup() {
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, 0);
}
void loop() {
analogWrite(ledPin, brightness); // light at certain brightness
//delay(5); // wait a bit, stay at this level so we can see the effect!
delay(50); // longer delay means much slower change from bright to dim
if (direction == 1) // determine whether to go brighter or dimmer
brightness += 1;
else
brightness -= 1;
if (brightness == 255) // switch direction for next time
{
direction = -1;
delay(extra_delay); // extra delay at maximum brightness
}
if (brightness == 0) // switch direction, go brighter next time
{
direction = 1;
delay(super_delay); // super long delay at minimum brightness
}
}
This will go brighter, then dim, and repeat. The delay is very important -- you can reduce it or lengthen it, but without it, the change happens so fast you can't see it by eye, only on an oscilloscope. Hope this helps you!
EDIT:
Added a "super delay" at minimum brightness for measurement of that level.
One thing to keep in mind is that pulse-width modulation like this still gives full driving voltage from the output pin. PWM just alters the ratio of the time the pin is high vs. low. On this Aduino, it's still a voltage swinging instantly and quite rapidly between 0V and 3.3V. To get a true analog voltage from this output, one needs some circuitry to filter the highs and lows of PWM into a smoother average DC voltage. If you want to pursue that, search for "RC low-pass filter" or visit a site like this one.

blinking all led at a time in arduino uno

** i want to turn on all 3 led'd at once then wait for sometimes(10 or 20 seceonds whatever) and then go off all 3 led;'s at a time **
here is my code:
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW);
digitalWrite(13, LOW);
digitalWrite(13, LOW);// turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
but its not working.
so, how i can turn all led on at a time and of at a time???

Boiling water (hacking into Kettle)using Arduino UNO and Ultrasonic sensor and Temperature sensor

I am making this machine thing(using arduino) that uses ultrasonic sensor to detect if you are close to it and then it starts boiling water (i hacked into this kettle for this function, and connected it to a relay), and once the temperature reaches a certain degree (using temperature sensor) it then stops the relay (that controls the power of the kettle), and tilts the kettle using the servo motor into a separate cup.
As of now my code easily turns on the relay and the kettle when it detects that the temperature of water is not hot enough, but after the temperature has reached a certain amount (i used 35 in this case just as a try) the servo wouldn't stop doing the rotation. The code makes it rotate at the three degrees and then it should stop (right?) but then it keeps rotating. Is there any way to fix this? Also, how do i finish the rotation part and make the program go on to use the ultrasonic sensor again and begin the process?
(FYI i am using a DF Robot or Seeed Studio's Ultrasonic sensor and temperature sensor and a 5 kg servo motor)
I am using arduino's library for relay control, ping library for the ultrasonic sensor, and temperature sensor
#include <Servo.h>
#include <SoftwareSerial.h>
int val; //
int tempPin = 1;
int relaypin = 13;
Servo myservo;
const int pingPin = 7;
int ledpin = 10;
void setup()
{
Serial.begin(9600);
pinMode(relaypin, OUTPUT); // taking relay input
myservo.attach(2);
myservo.write(90); // servo position
pinMode(ledpin, OUTPUT);
}
void loop()
{
long duration, cm; //*following code is for ultrasonic sensor
pinMode ( pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(1);
digitalWrite(pingPin, HIGH);
delayMicroseconds(2);
digitalWrite(pingPin, LOW);
pinMode (pingPin, INPUT);
duration = pulseIn (pingPin, HIGH);
cm= microsecondsToCentimeters(duration);
val = analogRead(tempPin);
float mv = ( val/1024.0)*5000;
float temp = mv/10;
//float farh = (temp*9)/5 + 32; *last line for ultrasonic sensor
//digitalWrite(relaypin, HIGH); //start the boiling
//delay (10);
if (cm <= 20)
{
if (temp <= 27)
{
digitalWrite(relaypin, HIGH); //start the machine
// myservo.write(75); //tilting the servo
// delay (2000); //pause for 2 seconds
// myservo.write(65);
// delay (2000); //pause for 2 seconds
// myservo.write(45);
// delay (2000);
// myservo.write(35);
// delay (2000);
// myservo.write(90);
// delay(5000);
}
else if(temp >= 35)
{
digitalWrite(relaypin, LOW); //stops the machine
delay(5000);
myservo.write(75); //tilting the servo
delay (2000); //pause for 20 seconds
myservo.write(65);
delay (2000); //pause for 20 seconds
myservo.write(45);
delay (2000);
myservo.write(35);
delay (2000);
myservo.write(90);
delay(5000);
}
}
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
Could it be that after the servo did the rotation the temperature is still >= 35? In that case the rotation code will be executed again and again until temp is falling below 35.
BTW: in your code you have a delay(2000) but the comment says // pause for 20 seconds. In fact you are only delaying for 2 seconds here. Maybe that's another reason why you get unexpected behavior? If you just wait long enough with the kettle being turned off the temperature is falling to a level which will not trigger the rotation code again.
Regarding beginning the process again: I'm not sure if you are aware that the code in loop() is just repeatedly executed until you turn off the Arduino. So as soon as the temperature is <= 27 and you are close enough to the ultrasonic sensor the code for starting the machine is just executed again.
Revised code:
(note: Thank you for your response, Josef. so i ended up changing the code and somehow made it run the way i wanted it to, to some extent. I used a counter variable to end the loop but I was wondering if there is a way to get into the loop again after exiting the loop? ideally i would want it to run everytime someone comes close and then repeat the process when someone comes close to it again. I realized the delay and fixed it, and same i know about the loop() function.)
#include <Servo.h>
#include <SoftwareSerial.h>
#define trigPin 8
#define echoPin 7
int val;
int tempPin = A0;
int relaypin = 13;
Servo myservo;
int ledpin = 10;
boolean complete = false;
void setup()
{
Serial.begin(9600);
pinMode(relaypin, OUTPUT); // taking relay input
myservo.attach(12);
myservo.write(90); // servo position
pinMode(ledpin, OUTPUT);
SensorSetup();
}
void loop()
{
int actualDistance = MeasureDistance();
Serial.print(actualDistance);
Serial.println(" cm");
delay(500);
val = analogRead(tempPin);
float mv = ( val/1024.0)*5000;
float temp = mv/10;
//float farh = (temp*9)/5 + 32; *last line for ultrasonic sensor
//digitalWrite(relaypin, HIGH); //start the boiling
//delay (10);
Serial.println(temp);
if (actualDistance <= 25)
{
while (temp >= 20 && temp <=45)
{
digitalWrite(relaypin, HIGH); //start the machine
Serial.println(actualDistance);
}
}
else if(actualDistance >= 20)
{
if (temp >= 55 && complete == false)
{
Serial.println(actualDistance);
digitalWrite(relaypin, LOW); //stops the machine
delay(5000);
myservo.write(75); //tilting the servo
delay (2000); //pause for 2 seconds
myservo.write(65);
delay (2000); //pause for 2 seconds
myservo.write(45);
delay (2000);
myservo.write(35);
delay (2000);
myservo.write(25);
delay (2000);
myservo.write(15);
delay (2000);
myservo.write(0);
delay (2000);
myservo.write(25);
delay (2000);
myservo.write(35);
delay (2000);
myservo.write(45);
delay (2000);
myservo.write(60);
delay (2000);
myservo.write(90);
delay(5000);
complete = true;
}
}
}
void SensorSetup(){
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
int MeasureDistance(){ // a low pull on pin COMP/TRIG triggering a sensor reading
long duration;
digitalWrite(trigPin, LOW); // Added this line
delayMicroseconds(2); // Added this line
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // Added this line
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
long distance = (duration / 2) / 29.1;
return (int)distance;
}

Arduino: How to eliminate thermocouple amplier noise

Scenario:
I m experimenting the thermocouple amplifier (SN-6675) with Arduino DUE.
After i'm included MAX6675 library, Arduino can measured room temperature.
However, Temp measured from arduino have 2 issues,
1) offset compare to "Fluke thermometer"
2) have tons of noise, and keep fluctuated after taking average of each 5 temperature sample.
eg, Fluke thermometer got 28.9C at room temp, arduino got 19.75~45.75C
Question: Any method/filter to reduce the measured noise, and gives a steady output?
Codes is attached for reference.
#include <MAX6675.h>
//TCamp Int
int CS = 7; // CS pin on MAX6675
int SO = 8; // SO pin of MAX6675
int SCKpin = 6; // SCK pin of MAX6675
int units = 1; // Units to readout temp (0 = ˚F, 1 = ˚C)
float error = 0.0; // Temperature compensation error
float tmp = 0.0; // Temperature output variable
//checking
int no = 0;
MAX6675 temp0(CS,SO,SCKpin,units,error); // Initialize the MAX6675 Library for our chip
void setup() {
Serial.begin(9600); // initialize serial communications at 9600 bps:
}
void loop() {
no= no + 1;
tmp = temp0.read_temp(5); // Read the temp 5 times and return the average value to the var
Serial.print(tmp);
Serial.print("\t");
Serial.println(no);
delay(1000);
}
Any method/filter to reduce the measured noise, and gives a steady output?
The Kalman filter is pretty much the standard method for this:
Kalman filtering, also known as linear quadratic estimation (LQE), is an algorithm that uses a series of measurements observed over time, containing noise (random variations) and other inaccuracies, and produces estimates of unknown variables that tend to be more precise than those based on a single measurement alone.
If your background isn't maths, don't be put off by the formulas that you come across. In the single-variable case like yours, the filter is remarkably easy to implement, and I am sure googling will find a few implementations.
The filter will give you an estimate of the temperature as well an estimate of the variance of the temperature (the latter gives you an idea about how confident the filter is about its current estimate).
You may want to go for a simpler averaging algorithm. This is not as elegant as a low pass algorithm but may be adequate for your case. These algorithms are plentiful on the web.
You can monkey around with the number of samples you take to balance the compromise between latency and stability. You may want to start with 10 samples and work from there.

Resources