Having problems with relay actuating

I’m using an uno with a DS18B20 one wire temp sensor and a generic opto-isolated 2 relay board like this:

https://arduino-info.wikispaces.com/RelayIsolation

My goal is to read temperature and pass that as “Input” to the PID. The PID actuates a relay to turn on a light bulb, which provides heat. The sensor & light bulb are in a styrofoam cooler. This is a proof of concept for making an incubator.

My problem is that the relay is not actuating when I put all the code together.

The wiring is fairly simple: DS18B20 on pin 3, relay “In0” on pin 6. Relay JD-Vcc is jumpered to Vcc and Arduino 5V & GND are wired to the relay board Vcc & GND (I’m not using full isolation at the moment.) Relay is active when pin is LOW.

Not changing the hardware configuration…

This works:

// This Arduino sketch reads DS18B20 "1-Wire" digital
// temperature sensors.
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress insideThermometer = { 0x28, 0xA1, 0xF6, 0xE0, 0x04, 0x00, 0x00, 0x98 }; // this is my address


void setup(void)
{
  // start serial port
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(insideThermometer, 10);

}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  } else {
    Serial.print("C: ");
    Serial.print(tempC);
    Serial.print(" F: ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
  }
}

void loop(void)
{
  delay(2000);
  Serial.print("Getting temperatures...\n\r");
  sensors.requestTemperatures();
 
  Serial.print("Inside temperature is: ");
  printTemperature(insideThermometer);

  Serial.print("\n\r\n\r");
}

and this works:

#define RELAY1 6                    
 
void setup()
{    
// Initialise the Arduino data pins for OUTPUT
   pinMode(RELAY1, OUTPUT);       
}
 
void loop()
{
   digitalWrite(RELAY1,LOW);           // Turns ON Relays 1
   delay(2000);                        // Wait 2 seconds
   digitalWrite(RELAY1,HIGH);          // Turns Relay Off 
   delay(2000);                        // Wait 2 seconds

}

and this works:

#define RelayPin  6                      

int windowSize = 4000;
unsigned long windowStartTime;
double Output;

void setup()
{    
   // Initialise the Arduino data pins for OUTPUT
   pinMode(RelayPin, OUTPUT);
   
   // start serial port
   Serial.begin(9600);
   
   windowStartTime = millis();
   
   Output = 2000; // pretend we have a 50% duty cycle
   
   
}
 
void loop()
{
  unsigned long now = millis();
  if (now - windowStartTime > windowSize)
  {  windowStartTime += windowSize;
     Serial.print("shifting the window...");
     Serial.print("\n\r\n\r");
  }
  if (Output > now - windowStartTime)
  {  digitalWrite(RelayPin,HIGH);
     Serial.print("Relay Pin is HIGH");
     Serial.print("\n\r\n\r");
  }
  else
  {  digitalWrite(RelayPin,LOW);
     Serial.print("Relay Pin is LOW");
     Serial.print("\n\r\n\r");
  }
  Serial.print(now - windowStartTime);
  Serial.print("\n\r\n\r");
  Serial.print(Output);
  Serial.print("\n\r\n\r");
}

but this does not work:

// This Arduino sketch reads a waterpoof DS18B20 temperature sensor
// and passes that value to the "input" of a PID instance.
// The PID then cycles a relay connected to a heater to
// achieve the "setpoint" temperature.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v1.h>

#define RelayPin 6
#define ONE_WIRE_BUS 3  // Data wire is plugged into pin 3 on the Arduino

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress peltierTemp = { 0x28, 0xA1, 0xF6, 0xE0, 0x04, 0x00, 0x00, 0x98 }; // this is my address


//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

int windowSize = 5000;
unsigned long windowStartTime;

void setup()
{
  // start serial port
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(peltierTemp, 10);


  windowStartTime = millis();

  //initialize the variables we're linked to
  Setpoint = 25;    // why not make a 37 degree incubator...?

  //tell the PID to range between 30 and the full window size
  //Operarion Time(10ms) plus Release Time(5ms), doubled to 30ms
  //We're using an electromechanical relay. SSR may be faster!
  myPID.SetOutputLimits(30, windowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}


void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);  // here is where current temp is assigned to "tempC"
  Input = tempC;
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  } else {
    Serial.print("C: ");
    Serial.print(tempC);
  }
}


void loop()
{
  Serial.print("Getting temperatures...\n\r");
  sensors.requestTemperatures();
 
  Serial.print("Inside temperature is: ");
  printTemperature(peltierTemp);
  Serial.print("\n\r\n\r");

  // Setting input moved into the printTemperature function
  myPID.Compute();
  
  // turn the output pin on/off based on pid output
  unsigned long now = millis();
  if (now - windowStartTime > windowSize)
  {  windowStartTime += windowSize;
     Serial.print("shifting the window...");
     Serial.print("\n\r\n\r");
  }
  if (Output > now - windowStartTime)
  {  digitalWrite(RelayPin,HIGH);
     Serial.print("Relay Pin is HIGH");
     Serial.print("\n\r\n\r");
  }
  else
  {  digitalWrite(RelayPin,LOW);
     Serial.print("Relay Pin is LOW");
     Serial.print("\n\r\n\r");
  }
  Serial.print(now - windowStartTime);
  Serial.print("\n\r\n\r");
  Serial.print(Output);
  Serial.print("\n\r\n\r");

}

The code is not polished, but the section at the bottom is pasted directly from the relayWithMillis example above it.

Could there be interference between the I2C bus on pin 3 and the relay on pin 6?
Serial output indicates that the state of pin 6 is changing and a multimeter clipped to pin 6 confirms this.
Serial output also indicates that the PID algorithm is behaving as expected.
Tried both USB and external power + USB (to debug.) The relay should only pull a few mA from pin6 to trigger and the coil only pulls ~72 mA from Arduino 5V supply. Could it be a timing issue?

I am perplexed!! Thank you for any suggestions.

Timing is the first thing I thought of. The loop speed is very high so if you are turning the relay on/off quickly, you will have problems. NB I have not analysed the code.

Weedpharma

To eliminate any possible power issues, I would at least use a separate supply for the relay board (JVCC). For full isolation, just remove the jumper and use GND and JVCC for the separate 5V supply.

The only connections to the Arduino would be In0 and VCC. There should be no GND connection made from the relay board to Arduino.

I did try a separate (9V battery) supply and full isolation.

A 9V battery can't supply sufficient current. Use a separate 5V supply for the relay board. For full isolation, the jumper is removed and there is no ground wire connected from the relay board to the Arduino.

dlloyd: A 9V battery can't supply sufficient current. Use a separate 5V supply for the relay board. For full isolation, the jumper is removed and there is no ground wire connected from the relay board to the Arduino.

I isolated the arduino by wiring as in your diagram and hooked up a separate 5V power supply to power the coil. Still doesn't work.

If you look at the bottom 2 code examples above, the 2nd to last one works to actuate the relay using isolated power and arduino 5V power. The last code example has the previous code embedded in it, but does not work under either condition. Even though the last example doesn't actuate the relay, my debugging serial prints indicate that the pin is cycling between low & high.

Could the I2C bus on pin 3 be interfering somehow?

I2C is nothing to do with pin 3.

Get a multimeter and measure the voltages, that is your eyes and ears for electronics.

MarkT:
I2C is nothing to do with pin 3.

Get a multimeter and measure the voltages, that is your eyes and ears for electronics.

I have a multimeter and an analog oscilloscope.

From my 1st post above:

“Serial output indicates that the state of pin 6 is changing and a multimeter clipped to pin 6 confirms this.”

My meter reads 0V and 5V alternately on pin 6, but the relay isn’t tripping with the last set of code when everything is hooked up. I’m going to either start commenting out lines until it works or better, rewrite everything. I would just like to understand why it is not working. Thank you for the info on I2C.

If the pin voltages are as expected, your problem is with the relay module and its power supply, clearly.

MarkT: If the pin voltages are as expected, your problem is with the relay module and its power supply, clearly.

If that is the case, then why does this code run as expected (i.e. relay cycles every 2") without altering the hardware setup?

#define RelayPin  6                      

int windowSize = 4000;
unsigned long windowStartTime;
double Output;

void setup()
{    
   // Initialise the Arduino data pins for OUTPUT
   pinMode(RelayPin, OUTPUT);
   
   // start serial port
   Serial.begin(9600);
   
   windowStartTime = millis();
   
   Output = 2000; // pretend we have a 50% duty cycle
   
   
}

void loop()
{
  unsigned long now = millis();
  if (now - windowStartTime > windowSize)
  {  windowStartTime += windowSize;
     Serial.print("shifting the window...");
     Serial.print("\n\r\n\r");
  }
  if (Output > now - windowStartTime)
  {  digitalWrite(RelayPin,HIGH);
     Serial.print("Relay Pin is HIGH");
     Serial.print("\n\r\n\r");
  }
  else
  {  digitalWrite(RelayPin,LOW);
     Serial.print("Relay Pin is LOW");
     Serial.print("\n\r\n\r");
  }
  Serial.print(now - windowStartTime);
  Serial.print("\n\r\n\r");
  Serial.print(Output);
  Serial.print("\n\r\n\r");
}

That really is the heart of my question !

The relay works fine in a simple scenerio. In the context of my code where I'm reading a DS18B20, passing that as input to a PID function, and trying to control the relay based on the PID output--the relay doesn't work. It must be something about the extra code &/or a timing issue. Maybe I should post this in the programming section?

PROBLEM SOLVED!!!

I forgot to copy these lines to my more complicated program:

 // Initialise the Arduino data pins for OUTPUT
  pinMode(RelayPin, OUTPUT);

DUH!!!

The interesting thing is that even when I did not have the pinMode(RelayPin, OUTPUT); statement declaring the RelayPin to be used for OUTPUT, the voltage of the pin still cycled between ~5 V and 0 V relative to GND when called by digitalWrite. That cycling was not sufficient to trip the relay, but fooled me good since my meter picked it up.

if (Output > now - windowStartTime)
  {  digitalWrite(RelayPin,HIGH);
     Serial.print("Relay Pin is HIGH");
     Serial.print("\n\r\n\r");
  }
  else
  {  digitalWrite(RelayPin,LOW);
     Serial.print("Relay Pin is LOW");
     Serial.print("\n\r\n\r");

Thank you for all who chimed in and sorry for the bother.

Hopefully the information that the voltage of a pin (that is set by default to INPUT) can be manipulated by calling digitalWrite on it is vaguely interesting / useful...