Hallo Allemaal.

Ik had een vraag betreft mijn pas aangekochte Arduino UNO.
Erg leuk om ermee te oefenen trouwens!!

Nu had ik de microcontroller gekocht om de temperatuur van mijn terrariums te controleren, en tegelijkertijd de gegeven op te slaan in een bestand.

Het opslaan in een bestand geeft geen problemen, maar ik stuit
elke keer weer op het zelfde probleem;
Ik heb een relais aangesloten zoals de Sparkfun CIRC-11 dit beschrijft.

http://img688.imageshack.us/img688/6783/naamloosgpa.jpg

Hierbij heb ik een LM35 temperatuur sensor toegevoegt aan de 5V, GND en A0.

De code:

int temperaturePin = 0; 
int klik = 13;


void setup()
{
  Serial.begin(9600);  
  pinMode (klik, OUTPUT);
 pinMode (temperaturePin, INPUT);
}

void loop()                     
{
float temperature = getVoltage(temperaturePin);  
temperature = (temperature - .5) * 100;          
                                                  
Serial.println(temperature);      

if (temperature > 24.00)             
  {
    digitalWrite (klik, LOW); 
  }
else if (temperature <= 24.00)             
  {
    digitalWrite (klik, HIGH);   
  }
}

float getVoltage(int pin){
  analogRead(pin);
  delay(1000);
  return (analogRead(pin) * .0048828125);                                
}

Nu gaat eigenlijk alles goed, behalve als de temperatuur onder de 24 graden blijft, dan schakelt het relais elke seconde aan en uit, dit
om en om, dus aan, uit, aan, uit, ect.

Adem ik nu op de sensor, waardoor de temperatuur omhoog gaat, dan schakelt arduino correct het relais uit.

Iemand enig idee wat ik hier fout doe?

Alvast bedankt!!!

Ik heb al eens ergens gelezen dat je bij een temperatuursensor die een relais aanstuurt een "overgangszone" in de programmacode moet maken van enkele graden, omdat anders de controller constant denkt dat hij vlak boven of vlak onder de temperatuur komt.

Je zult wat hysterese moeten in bouwen. Dus:


  loop () 
{
  static unsigned char state;
  ...
  if (temperature > 24.5) 
     state = LOW;
  if (temperature < 23.5)
     state = HIGH;

  digitalWrite (klik, state);   
}

De plek waar jij je "delay()" hebt staan is niet handig. Ik had hem daar niet verwacht en haast over het hoofd gezien.

Waarschijnlijk zit de temperatuur precies rond het omschakelpunt en klapt dus telkens om. De oplossing is, zoals rew zegt, door hysterese in te bouwen.

Op 3 april 2011 12:58:41 schreef BBNick:



float getVoltage(int pin){
  analogRead(pin);
  delay(1000);
  return (analogRead(pin) * .0048828125);                                
}

Waarom wordt analogRead trouwens twee keer aangeroepen?

@rew, ik zou trouwens van de tweede if een else if maken, dat scheelt weer processortijd :) (en waar je nu bij digitalWrite 'HIGH' hebt staan moet state staan lijkt mij)

Het gaat een stuk beter nu, het schakelen gaat nu goed, wel heb ik het idee wanneer het relais uitschakelt, dat de temperatuur sensor ineens een onjuiste, hogere waarde weergeeft, en dit blijft doen todat het relais weer inschakelt... Enig idee waardoor dit kan?
Indien ik dit euvel opgelost heb, kan ik wellicht een kleinere marge gebruiken tussen de temperaturen voor aan en/off uit-schakelen.

Bedankt!

Ik heb even erg kritisch gekeken, de marge tussen het inschakelen en uitschakelen van het relais, is ongeveer 2 graden.

Is dit misschien een voeding probleem?

Zal het misschien beter worden als ik het relais extern voedt d.m.v. een losse adapter?
Dan heeft het schakelen van het relais wellicht geen invloed op de temp sensor.
Is natuurlijk een idee haha, wat vinden jullie ervan?

Mijn huidige code:


int temperaturePin = 0; 
int klik = 13;


void setup()
{
  Serial.begin(9600);  
  pinMode (klik, OUTPUT);
 pinMode (temperaturePin, INPUT);
}

void loop()                     
{
float temperature = getVoltage(temperaturePin);  
temperature = (temperature - .5) * 100;          
                                                  
Serial.println(temperature); 

static unsigned char state;
if (temperature > 27) 
     state = LOW;
 else if (temperature <= 25)
    state = HIGH;

 digitalWrite (klik, state);    
  
        }
  
                                 


float getVoltage(int pin){
  analogRead(pin);
  delay(1000);
  return (analogRead(pin) * .0048828125);                                
}

Mijn beperkte analoge kennis zegt dat da wel eens de oorzaak zou kunnen zijn. Wanneer het relais schakeld zakt de spanning wat in, waardoor ook de referentie spanning van de AVR inzakt.

Dit zou je kunnen oplossen door een flinke elco over de voeding te zetten, die dan de spanningsdipjes opvangt.

Wat gebruik je als spanningsbron?

Oh, en je roept nog steeds tweemaal analogRead aan in je getVoltage functie. Dat heeft geen enkel nut! Tevens kun je (zoals rew al eerder aangaf) de delay beter in de loop functie zetten, dat maakt je code beter leesbaar. Al maakt het voor de werking niet uit.

Bedankt voor je reactie,

Ik heb het aangepast, momenteel wordt de analogRead 1 maal aangeroepen.
Momenteel gebruik ik de standaard USB als voeding.
Ik weet zo het amperage niet van een USB aansluiting, maar het zal vast niet veel zijn

Door een externe 9VDC bron te gebruiken, en vervolgens de V1n op de arduino te gebruiken voor het relais, en gewoon de 5v voor de sensor, werk alles naar behoren.

Op 1 of andere manier was het het relais dus die zorgde voor het grote verschil.

Ik kan nu schakelen met 1 graad celsius overlapping, wat ruim voldoende is.

Thanx!!

Op 3 april 2011 13:34:25 schreef stereohead:
Waarom wordt analogRead trouwens twee keer aangeroepen?

Het is slightly tricky om de eerste meting na het switchen van de ingang-selectie direct goed te krijgen. Je moet dan voldoende wachten. En/of een dummy conversie doen. Kortom, als je switched, even wacht, en dan
nogmaals leest, is hij altijd goed....

@rew, ik zou trouwens van de tweede if een else if maken, dat scheelt weer processortijd :)

En dat staat pal achter een serial.println (duurt millisecondes) en een "delay (1000)" duurt een hele seconde.

Het gaat je pak 'm beet 3 clock cycli schelen als ie kleiner is dan 27. Tja. Ik vind de code mooier, de symmetrie straalt er beter vanaf als je het schrijft zoals ik deed. Kortom, ik heb die 3 cycles er wel voor over voor wat leesbaarheid in de C-code.

(en waar je nu bij digitalWrite 'HIGH' hebt staan moet state staan lijkt mij)

Ooops! fixed!.