Arduino Forum

Using Arduino => Programming Questions => Topic started by: Morke on May 22, 2016, 03:50 am

Title: First code
Post by: Morke on May 22, 2016, 03:50 am
Hi everyone!

Well, I made the jump and wrote my first code. I was wondering if you could check it and tell me your thoughts

The idea is to control 4 heat tapes under 4 different reptiles terrariums. I have 4 LM35 temp sensors connected to the Analog pins and a 4 Relay module connected to the Digital pins. I found different codes and made a "frankenstein" monster.
If this works, I'm gonna upgrade it with an LCD to read temps and, after that, a WiFi Module to be able to check the terrariums from my PC, but that's gonna take time, having in mind I have no idea of C++ language...

Anyway, here's the code. Please share your thoughts with me so I can improve it:

Code: [Select]

float tempC1;
int reading1;
int tempPin1 = A1;
#define RELAY1  6   

float tempC2;
int reading2;
int tempPin2 = A2;
#define RELAY2  7

float tempC3;
int reading3;
int tempPin3 = A3;                       
#define RELAY3  8

float tempC4;
int reading4;
int tempPin4 = A4;                       
#define RELAY4  9


void setup()
{
analogReference(INTERNAL);
Serial.begin(9600);
pinMode(RELAY1, OUTPUT);       
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
}

void loop()
{
reading1 = analogRead(tempPin1);
tempC1 = reading1 / 9.31;
if (tempC1 < 24){
  digitalWrite(RELAY1,LOW);
}

reading2 = analogRead(tempPin2);
tempC2 = reading2 / 9.31;
if (tempC2 < 24){
  digitalWrite(RELAY1,LOW);
}

reading3 = analogRead(tempPin3);
tempC3 = reading3 / 9.31;
if (tempC3 < 24){
  digitalWrite(RELAY1,LOW);
}

reading4 = analogRead(tempPin4);
tempC4 = reading4 / 9.31;
if (tempC4 < 24){
  digitalWrite(RELAY1,LOW);
}



Serial.println(tempC1);
delay(1000);
Serial.println(tempC2);
delay(1000);
Serial.println(tempC3);
delay(1000);
Serial.println(tempC4);
delay(1000);
}

Title: Re: First code
Post by: larryd on May 22, 2016, 03:59 am
Get rid of your delay()s.
Do you really need floats?
If a byte type works don't use an int
Maybe add hysteresis to your control sections.
When do the heaters turn off?
You only use RELAY1  :o
Title: Re: First code
Post by: sterretje on May 22, 2016, 04:14 am
Your a little inconsistent in the declaration of the pins. You use an int for the temp pins but a #define for the relay pins.

Code: [Select]

float tempC1;
int reading1;
int tempPin1 = A1;
#define RELAY1  6


Make that either
Code: [Select]

float tempC1;
int reading1;
#define tempPin1  A1
#define RELAY1  6

Or
Code: [Select]

float tempC1;
int reading1;
int tempPin1 = A1;
int RELAY1 = 6;


As it's very unlikely that you will ever have over 256 pins, you can change the type in the latter to byte (instead of int).
If you want the compiler to warn you if you try by accident to change the pin number, add the const keyword to it
Code: [Select]

float tempC1;
int reading1;
const byte tempPin1 = A1;
const byte RELAY1 = 6;


You also might want to make sure in setup that the relays are off (or on); add a digitalWrite for each relay in setup().


The biggest flaw in your code is that you never switch the relays off. In the below, I've added this; the heater switches off again at 25 degrees.

Code: [Select]

  reading1 = analogRead(tempPin1);
  tempC1 = reading1 / 9.31;
  if (tempC1 < 24) {
    digitalWrite(RELAY1, LOW);
  }
  else if(tempC1 > 25)
  {
    digitalWrite(RELAY1, HIGH);
  }

Note that hard-coded values are a mission to maintain. You have to dig through your code to find thhe temperature limit.

You can use something like
Code: [Select]

#define LOWER 24
#define UPPER 25

And change the above to
Code: [Select]

  reading1 = analogRead(tempPin1);
  tempC1 = reading1 / 9.31;
  if (tempC1 < LOWER) {
    digitalWrite(RELAY1, LOW);
  }
  else if(tempC1 > UPPER)
  {
    digitalWrite(RELAY1, HIGH);
  }


You can also store your pins, readings etc in arrays. And even neater might be a struct. But that's a little more advanced.

That way you can loop through the reading of the sensors and the setting of the relays.
Title: Re: First code
Post by: Morke on May 22, 2016, 05:31 am
Thank you a lot for your help, it's been very useful!

One question, how should I add hysteresis? I was thinking of making a mean with the last, say, 10 values, but that would make me create 10 more variables...
Title: Re: First code
Post by: larryd on May 22, 2016, 05:40 am
@sterretje has mentioned LOWER and UPPER limits and attached an example.

You could also use something like:
<limit
then
>limit+1
or
>limit+hysteresis
Title: Re: First code
Post by: ChrisTenone on May 22, 2016, 05:52 am
Hysteresis is where the value of the change is different going up than it is going down - there is a small bit of temperature (or whatever is being measured/controlled) overlap. It keeps an automated device from getting stuck in a 'switching off/switching on' loop it cant get out of.
Title: Re: First code
Post by: Rupert909 on May 22, 2016, 02:29 pm
This is possibly beyond your current understanding of C++, but the following code compiles and should be reasonably easy to follow. Creating a class and four instances of it, means you don't have to duplicate the code. This implementation also introduces an overlap of temperatures, so that the heaters don't get switched on and off too frequently.

Code: [Select]

class Heater {
  private:
    int switchOnBelowTemp;
    int switchOffAboveTemp;
    int tempPin;
    int relayPin;
  public:
    Heater (int switchOnBelowTemp, int switchOffAboveTemp, int tempPin, int relayPin) {
      this->switchOnBelowTemp=switchOnBelowTemp;
      this->switchOffAboveTemp=switchOffAboveTemp;
      this->tempPin=tempPin;
      this->relayPin=relayPin;
     
      pinMode(tempPin, INPUT);
      pinMode(relayPin, OUTPUT);
      digitalWrite(relayPin, LOW);
    }
    void check() { // called from loop()
      int reading=analogRead(tempPin);
      float temp = reading / 9.31;
      if (temp < switchOnBelowTemp){
        digitalWrite(relayPin,HIGH);
      } else if (temp > switchOffAboveTemp) {
        digitalWrite(relayPin,LOW);
      }
    }
};

Heater h1(22,24,A1,6);
Heater h2(22,24,A2,7);
Heater h3(22,24,A3,8);
Heater h4(22,24,A4,9);

void setup() {
}

void loop() {
  h1.check();
  h2.check();
  h3.check();
  h4.check();
}


Sketch uses 1 870 bytes (6%) of program storage space. Maximum is 30 720 bytes.
Global variables use 43 bytes (2%) of dynamic memory, leaving 2 005 bytes for local variables. Maximum is 2 048 bytes.
Title: Re: First code
Post by: BulldogLowell on May 22, 2016, 02:44 pm
This is possibly beyond your current understanding of C++, but the following code compiles and should be reasonably easy to follow. Creating a class and four instances of it, means you don't have to duplicate the code. This implementation also introduces an overlap of temperatures, so that the heaters don't get switched on and off too frequently.

Code: [Select]


  public:
    Heater (int switchOnBelowTemp, int switchOffAboveTemp, int tempPin, int relayPin) {
      this->switchOnBelowTemp=switchOnBelowTemp;
      this->switchOffAboveTemp=switchOffAboveTemp;
      this->tempPin=tempPin;
      this->relayPin=relayPin;
      
      pinMode(tempPin, INPUT);
      pinMode(relayPin, OUTPUT);
      digitalWrite(relayPin, LOW);
    }

Agreed you are climbing up a steep curve, but you shouldn't forget that setting pinMode before setup isn't guaranteed to make that work.

you should create a method (i.e. begin()) to set the pinMode during setup().
Title: Re: First code
Post by: Rupert909 on May 22, 2016, 06:42 pm
...  you shouldn't forget that setting pinMode before setup isn't guaranteed to make that work.

you should create a method (i.e. begin()) to set the pinMode during setup().
Good point. Thank you!
Title: Re: First code
Post by: Morke on May 26, 2016, 08:56 pm
Thank you all for your help. I updated the code and now i'm investigating to add LCD and some wifi functions.


Classes are a bit over my head, but i'll try to transform the code once it's working.
Title: Re: First code
Post by: Morke on Jun 02, 2016, 07:45 pm
Ok so I have a problem and a question

First of all, once I uploaded the code, it started working BUT, the moment the If condition gets:
Code: [Select]

if (tempC1 < LOWER)
  {
  digitalWrite(RELAY1,LOW);
  }

The port stops working and I can't get any more readings until I change the COM number and replug the USB.
The program keeps running, because I can see the relay switching off and on, but the port bugs and gets me this Error message:

Error while setting serial port parameters: 9,600 N 8 1

What's going on?


The other question is:
The temps change quite a bit and I want to have an Array to calculate AVG temperature for the last, let's say, 20 readings and make THAT variable the one that the IF condition reads to get on/off the relay.
How can I make an operation to read the LAST 20 readings and keep erasing old ones and recording new ones?



Thank you all
Title: Re: First code
Post by: UKHeliBob on Jun 02, 2016, 07:58 pm
Quote
once I uploaded the code,
Please post teh code here
Title: Re: First code
Post by: larryd on Jun 02, 2016, 08:18 pm
Also show your schematic.

.
Title: Re: First code
Post by: Morke on Jun 05, 2016, 08:48 pm
I'm not sure how to draw the schematics.. i'll try my best and then upload them.
The Arduino powers the 4 LM35 temp sensors, and a YwRobot Power supply powers the 4 relay module externaly to avoid issues.
I placed a 1k resistor and 100uF between each output and GND pins on the LM35 sensors to clear the signal.

The bug happens like this:
I connect the USB to the Arduino and I turn on the External Power supply to power the 4 Relay Module. I open the Serial Port Monitor and start checking the temp readings. The program starts working fine and all the temps keep coming through the Serial Monitor. BUT once one of the relays turns off and then turns ON AGAIN, the Monitor stops working and no more temps get through it. I know the program keeps working because I can see and hear the relay switching off and on while I check the temperatures with an external temp sensor. The problem is in the Serial Monitor.
To get it working again, I have to change the COM port Number the Arduino was on, unplug and then plug again the Arduino and voila, it works again UNTIL the same situation happens again and it gets bug.

Here's the code:
Code: [Select]

float tempC1;
int reading1;
const byte tempPin1 = A1;
const byte RELAY1 = 6;

float tempC2;
int reading2;
const byte tempPin2 = A2;
const byte RELAY2 = 7;

float tempC3;
int reading3;
const byte tempPin3 = A3;                       
const byte RELAY3 = 8;

float tempC4;
int reading4;
const byte tempPin4 = A4;                       
const byte RELAY4 = 9;

#define LOWER 26
#define UPPER 32

void setup()
{
analogReference(INTERNAL);
Serial.begin(9600);
pinMode(RELAY1, OUTPUT);       
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, HIGH);
digitalWrite(RELAY4, HIGH);
}

void loop()
{
reading1 = analogRead(tempPin1);
tempC1 = reading1 / 9.31;
if (tempC1 < LOWER)
  {
  digitalWrite(RELAY1,LOW);
  }
else if (tempC1 > UPPER)
  {
    digitalWrite(RELAY1, HIGH);
  }

reading2 = analogRead(tempPin2);
tempC2 = reading2 / 9.31;
if (tempC2 < LOWER)
  {
  digitalWrite(RELAY2,LOW);
  }
else if (tempC2 > UPPER)
  {
    digitalWrite(RELAY2, HIGH);
  }
 
reading3 = analogRead(tempPin3);
tempC3 = reading3 / 9.31;
if (tempC3 < LOWER)
  {
  digitalWrite(RELAY3,LOW);
  }
 else if (tempC3 > UPPER)
  {
    digitalWrite(RELAY4, HIGH);
  }

reading4 = analogRead(tempPin4);
tempC4 = reading4 / 9.31;
if (tempC4 < LOWER)
  {
  digitalWrite(RELAY4,LOW);
  }
else if (tempC4 > UPPER)
  {
    digitalWrite(RELAY4, HIGH);
  }


Serial.println(tempC1);
delay(1000);
Serial.println(tempC2);
delay(1000);
Serial.println(tempC3);
delay(1000);
Serial.println(tempC4);
delay(1000);
}

Title: Re: First code
Post by: UKHeliBob on Jun 05, 2016, 08:56 pm
Quote
The Arduino powers the 4 LM35 temp sensors, and a YwRobot Power supply powers the 4 relay module externaly to avoid issues.
Have the two supplies got a common GND ?
Title: Re: First code
Post by: Morke on Jun 05, 2016, 09:54 pm
Have the two supplies got a common GND ?
No, that would defeat the purpose of being isolated from each other and the Arduino could be damaged if something happened to the Relays.
Title: Re: First code
Post by: Rupert909 on Jun 05, 2016, 10:23 pm
No, that would defeat the purpose of being isolated from each other and the Arduino could be damaged if something happened to the Relays.
Lets see. The Arduino has a power supply, usually USB, at least while developing, then later perhaps a cell phone charger. Let's call this ArduinoPower.

Then there are the relays. Relays have two sides. There is the control connection and GND, and there is the controlled pins, 2 or 3 of those.

Now, are we talking solid-state relays that require very little current, say less than 30-40 mA, and are happy to work on 5V, or are we talking mechanical ones, which may even require 12V to operate, and definitely require more current than an Arduino pin can supply?

I seem to recall you saying something about your Arduino having to be reset, following an event involving the relays? Might this possibly be due to excessive current draw?

So ... if the Arduino can not control the relays directly, you will need an additional power supply for that, controlled via some transistor (MOSFET or other). Let's call that power supply RelayControl. Now, RelayControl and ArduinoPower must have common GND, for this to work.

If the Arduino directly controls the relay, then still the control-side of the relay must be connected to ArduinoPower, for common reference. Voltage is voltage only relative to something.

Then, finally, we come to the business end of the relays, the load to be switched on and off, and consequently requiring a power supply of its own. This power supply may be the same that I called RelayControl. But it may also be separate. Lets call it ActionPower, as it powers the "action".

(cheesy)

If ActionPower is separate from RelayControl, then at least for mechanical relays, this part may well exist electrically isolated from the control side, and needs not share GND with the beforementioned two. This is because (mechanical) relays are simple switches.

If ActionPower and RelayControl are one and the same, which means it is used both to control the relays, with transistor between relay and Arduino, and run the "action", then it must share GND with ArduinoPower.

As for solid state relays, I've never used those, so they may have other requirements.

So there we are. Any questions?? :-)

[Edited]
Title: Re: First code
Post by: Morke on Jun 06, 2016, 04:36 am
It's a mechanical Relay, but anyway that's not the issue. The problem seems to be related to the Serial print..... that's the only thing that bugs. The arduino keeps working.
Title: Re: First code
Post by: Whandall on Jun 06, 2016, 04:46 am
It's a mechanical Relay, but anyway that's not the issue.
If you know what the issue is, why ask us?
Title: Re: First code
Post by: UKHeliBob on Jun 06, 2016, 09:11 am
Are there diodes across the relays to prevent back EMF when they turn off ?
Title: Re: First code
Post by: Morke on Jun 07, 2016, 12:57 am
If you know what the issue is, why ask us?
Common ground (or not) is not the issue. I've tried both setups with no visible change. The bug happens no matter the relays and arduino share a power supply or have different ones with or without common ground.
I have no idea what's going on but at least that is not the issue.
Don't take me wrong, I didn't mean to sound agressive or disrespectful. If that's the case, please forgive me.





UKHeliBob
Im not sure about that, the 4 relay module is this one:
(http://mla-s2-p.mlstatic.com/modulo-de-relee-relay-opto-4-canales-5v-10a-arduino-pic-ptec-680001-MLA20256173556_032015-O.jpg)


I suspect the issue is within the code but that's only a hunch.....
Title: Re: First code
Post by: Rupert909 on Jun 07, 2016, 10:56 am
Common ground (or not) is not the issue. I've tried both setups with no visible change. The bug happens no matter the relays and arduino share a power supply or have different ones with or without common ground.
I have no idea what's going on but at least that is not the issue.
Don't take me wrong, I didn't mean to sound agressive or disrespectful. If that's the case, please forgive me.





UKHeliBob
Im not sure about that, the 4 relay module is this one:
(http://mla-s2-p.mlstatic.com/modulo-de-relee-relay-opto-4-canales-5v-10a-arduino-pic-ptec-680001-MLA20256173556_032015-O.jpg)


I suspect the issue is within the code but that's only a hunch.....

Do you hear clicks from it when engaging and disengaging, indicating the relays are mechanical?

I see the main block of pins containing GND, in1-4 and VCC. But there are three more pins, located by themselves. I See GND and VCC, but VCC is connected to a third pin, via a yellow jumper. What's written next to the third pin?

May it possibly be extra pins for supplying extra current, for driving the relays? My theory is still that your Arduino struggles with delivering the amount of current required to operate these. The jumper I suspect is used to select VCC from control-inputs row, for devices supplying enough current to drive the relays.

Title: Re: First code
Post by: Morke on Jun 07, 2016, 01:44 pm
Do you hear clicks from it when engaging and disengaging, indicating the relays are mechanical?

I see the main block of pins containing GND, in1-4 and VCC. But there are three more pins, located by themselves. I See GND and VCC, but VCC is connected to a third pin, via a yellow jumper. What's written next to the third pin?

May it possibly be extra pins for supplying extra current, for driving the relays? My theory is still that your Arduino struggles with delivering the amount of current required to operate these. The jumper I suspect is used to select VCC from control-inputs row, for devices supplying enough current to drive the relays.


Yes, I can hear the clicks.

The three more pins are for the external power supply

here's how the relays are powered:

(http://i.imgur.com/3fk9hHN.jpg)
Title: Re: First code
Post by: Rupert909 on Jun 07, 2016, 02:09 pm
Yes, I can hear the clicks.

The three more pins are for the external power supply

here's how the relays are powered:

(http://i.imgur.com/3fk9hHN.jpg)
No GND connection from Arduino?? Why not?
Title: Re: First code
Post by: dlloyd on Jun 07, 2016, 02:21 pm
No GND connection from Arduino?? Why not?
To use opto-isolation. The control lines provide path to GND when switched low.
Title: Re: First code
Post by: dlloyd on Jun 07, 2016, 02:23 pm
The following is a connection diagram and some test code. The operational and load test will sequentially turn on all relays then sequentially turn off all relays. Print monitor will display what part of the loop is running.

If you're still having USB problems, could try a different USB port and new or different USB cable.

Note that some USB ports might be current limited 100mA, 250mA, 500mA or other. The only way to guarantee 500mA is to use a USB hub with power adapter connected.   

(http://i.imgur.com/6m95zlV.png)


Test code:

Code: [Select]
/* 4 Relay Module configured for Opto-isolation
   Arduino pins 3 to 6 connected to IN1 to IN4
   Connections: http://i.imgur.com/6m95zlV.png */

void setup() {
  Serial.begin(115200);
  Serial.println("In sequence:");

  for (int i = 3; i <= 6; i++) {
    pinMode(i, INPUT_PULLUP);
    pinMode(i, OUTPUT); // defaults HIGH (relays off)
  }
}

void loop() {
  Serial.println("Relays turning ON ...");
  for (int i = 3; i <= 6; i++) {
    digitalWrite(i, LOW); // energize relays until all on
    delay(1000);
  }
  Serial.println("Relays turning OFF ...");
  for (int i = 3; i <= 6; i++) {
    digitalWrite(i, HIGH); // de-energize relays until all off
    delay(1000);
  }
}
Title: Re: First code
Post by: Rupert909 on Jun 07, 2016, 02:32 pm
I give up.
 :smiley-eek:
Title: Re: First code
Post by: dlloyd on Jun 07, 2016, 04:43 pm
Re-worked your code using arrays, faster printing (115200), only print once per second, added conditional temp limits for relay control and averaged readings (untested):

Code: [Select]
void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    sum[i] = analogRead(tempPin[i]);  // invalid
    sum[i] = 0;
    sum[i] += analogRead(tempPin[i]); // reading 1
    sum[i] += analogRead(tempPin[i]); // reading 2
    sum[i] += analogRead(tempPin[i]); // reading 3
    sum[i] += analogRead(tempPin[i]); // reading 4
    reading[i] = sum[i] / 4;          // averaged reading
    tempC[i] = reading[i] / 9.31;
    if (tempC[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (tempC[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  printCheck = millis() - lastPrintTime;
  if (printCheck >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}
Title: Re: First code
Post by: Morke on Jun 08, 2016, 01:10 am
Re-worked your code using arrays, faster printing (115200), only print once per second, added conditional temp limits for relay control (untested):

Code: [Select]
const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 26;

float tempC[4];
word reading[4];

word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    reading[i] = analogRead(tempPin[i]);
    tempC[i] = reading[i] / 9.31;
    if (tempC[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (tempC[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  printCheck = millis() - lastPrintTime;
  if (printCheck >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}

Now I give up  ;)
Woah, that's a lot of work. First of all thank you. I'll test it. I'm quite a newbie in programming so i'm struggling to understand all of the code.

But what I don't get is this part:
Code: [Select]

    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF


Why do you set the relay pin first to INPUT and right after that as OUTPUT?
Title: Re: First code
Post by: Whandall on Jun 08, 2016, 01:15 am
The INPUT_PULLUP functionality is activated by writing a HIGH to the output register.
So the Arduino output will start with a HIGH level, which is the relay off state.
Title: Re: First code
Post by: Morke on Jun 08, 2016, 01:31 am
The INPUT_PULLUP functionality is activated by writing a HIGH to the output register.
So the Arduino output will start with a HIGH level, which is the relay off state.
Oh, ok, so, the code uses INPUT_PULLUP to turn off all the relays the first time it runs, and then sets them as OUTPUT
It's like using digitalwrite(relay, HIGH) ?
Title: Re: First code
Post by: Whandall on Jun 08, 2016, 01:37 am
It writes to the port like digitalWrite() does.

Code: [Select]
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;

if (port == NOT_A_PIN) return;

// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);

if (mode == INPUT) {
uint8_t oldSREG = SREG;
                cli();
*reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
                cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
                cli();
*reg |= bit;
SREG = oldSREG;
}
}

Code: [Select]
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;

if (port == NOT_A_PIN) return;

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);

out = portOutputRegister(port);

uint8_t oldSREG = SREG;
cli();

if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}

SREG = oldSREG;
}
Title: Re: First code
Post by: larryd on Jun 08, 2016, 01:38 am
digitalwrite(relay, HIGH);
Seems a bit more intuitive.

.
Title: Re: First code
Post by: Whandall on Jun 08, 2016, 01:40 am
digitalwrite(relay, HIGH);
Seems a bit more intuitive.
Absolutely.
Title: Re: First code
Post by: dlloyd on Jun 08, 2016, 02:54 am
Oh, ok, so, the code uses INPUT_PULLUP to turn off all the relays the first time it runs, and then sets them as OUTPUT
It's like using digitalwrite(relay, HIGH) ?
Simply, the two configuration methods described prevent the relay pins from temporarily going LOW prior to entering the main loop. A relay pin temporarily going LOW could cause the relay to temporarily energize during setup.

Using one of the recommended setup methods, the pin does this:

1. Most pins are initially configured as INPUT (high impedance, floating). Relay remains OFF
2. Then the internal pullup gets enabled. The pin is weakly pulled to 5V. Relay remains OFF
3. Then the pin gets configured as OUTPUT. The pin is driven to 5V (the new default). Relay remains OFF

Now all relays are under your control in the main loop.
Title: Re: First code
Post by: Morke on Jun 08, 2016, 02:59 am
Ok so verifying the code this error pops up
Code: [Select]

Arduino: 1.6.8 (Windows 7), Board: "Arduino/Genuino Uno"

 In function 'void setup()':

temprelayfinal2:42: error: a function-definition is not allowed here before '{' token

 {

 ^

temprelayfinal2:75: error: expected '}' at end of input

 }

 ^

exit status 1
a function-definition is not allowed here before '{' token

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.



And it shows a red line here:

Code: [Select]

void setup()
[color=red]{[/color]
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
  }
}
Title: Re: First code
Post by: Whandall on Jun 08, 2016, 03:04 am
And the code above the failing definition of setup() has the error.
Title: Re: First code
Post by: Morke on Jun 08, 2016, 03:05 am
nvm i found the error
Title: Re: First code
Post by: Morke on Jun 08, 2016, 03:39 am
Would it be possible to add an array to make the relays work on Avg temperatures to smooth the readings?
Title: Re: First code
Post by: dlloyd on Jun 08, 2016, 03:48 am
Averaging might not be needed. Try adding an extra reading so there's 2 readings in a row. The first will be overwritten. The second will be more accurate because there's been a bit more time for the ADC value to settle.

Code: [Select]
reading[i] = analogRead(tempPin[i]);
reading[i] = analogRead(tempPin[i]);

EDIT: added above and some simple averaging for readings in code in reply#27.
Title: Re: First code
Post by: Morke on Jun 08, 2016, 03:42 pm
So I'm trying to add an average to smooth things out and to practice coding.

Could you correct the code? i'm sure it's wrong, but I want to know why.
Thank you



Code: [Select]

const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;

float tempC[4];
word reading[4];

const int numReadings = 50; //added
int readings[numReadings];                  //added
int readIndex = 0;                              //added
int total = 0;                                     //added
int average[4] = 0;[/color]                  //addded


word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
  }
 for (int thisReading = 0; thisReading < numReadings; thisReading++){ //added
    readings[thisReading] = 0;                                                        //added
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    reading[i] = analogRead(tempPin[i]);
    tempC[i] = reading[i] / 9.31;
    total[i] = total[i] - readings[readIndex];  //added
    readings[readIndex] = tempC[i]                            //added
    total[i] = total[i] + readings[readIndex]                 //added
    readIndex[i] = readIndex[i] + 1 ;                          //added
    if (readIntex[i] >= numReadings) {                        //added
      readIndex = 0;                                                //added 
    }
    average[i] = total[i] / numReadings;[/color]           //added
   
    if (average[i]< lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (average[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  printCheck = millis() - lastPrintTime;
  if (printCheck >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("TempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(average[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}
Title: Re: First code
Post by: PaulS on Jun 08, 2016, 03:56 pm
Does your code really have [ color=red ] crap in it?
Title: Re: First code
Post by: Morke on Jun 08, 2016, 04:39 pm
Does your code really have [ color=red ] crap in it?
Nah, I tried to highmark the changes and forgot to delete the bb code afterwards. Sorry
Title: Re: First code
Post by: Morke on Jun 09, 2016, 02:49 pm
Ok, a guy made it A LOT SIMPLER using Exponential smoothing:




Code: [Select]

const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;

const int numReadings = 64;
const word printInterval = 1000; // 1 second

float tempC[4];
unsigned long lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    digitalWrite(relayPin[i], HIGH);
    pinMode(relayPin[i], OUTPUT);
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    float raw_temp = analogRead(tempPin[i]) / 9.31;
    tempC[i] += (raw_temp - tempC[i]) / numReadings;  // filter
    if (tempC[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (tempC[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  if (millis() - lastPrintTime >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}