Hola! este es mi primer post y no se si este es el lugar correcto para ponerlo, si es asi, mil disculpas. Hace muy poco empecé a aprender a hacer cosas con Arduino y tengo un problema que no sé como resolver, asumo que logicamente me falta aprender y es por eso, pero tal vez sea algo simple que ustedes pueden ver y yo no.
El proyecto que estoy empezando es para hacer una incubadora para huevos de ave, tiene un control de temperatura y un motor para girar los huevos.
Está muy en los inicios, la idea es poner las cosas a trabajar y despues ir puliendo detalles, pero estoy atascado en que el motor paso a paso que le puse gira muy lento, cuando le saco al codigo la parte de leer la temperatura, todo anda normal.
Les dejo las lineas que tengo hechas hasta el momento.
PD: La asignacion de pines es algo rara porque estoy usando una placa STM32 blue pill pero en mis arduinos nano y uno hacen lo mismo.
Gracias desde ya.
#include <Wire.h>
#include "Adafruit_HTU21DF.h"
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>
#define BACKLIGHT_PIN 13
#define FULLSTEP 4
#define STEP_PER_REVOLUTION 2048
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_HTU21DF htu = Adafruit_HTU21DF();
AccelStepper stepper(FULLSTEP, 3, 1, 2, 0);
void setup() {
Serial.begin(9600);
stepper.setMaxSpeed(1000.0); // set the maximum speed
stepper.setAcceleration(200.0); // set acceleration
stepper.setSpeed(1000); // set initial speed
stepper.setCurrentPosition(0); // set position
stepper.moveTo(STEP_PER_REVOLUTION); // set target position: 64 steps <=> one revolution
htu.begin();
lcd.begin(16, 2);
lcd.backlight();
pinMode(6, OUTPUT);
lcd.setCursor(0, 0);
lcd.print("TEMPERATURA");
lcd.setCursor(0, 1);
lcd.print("HUMEDAD");
}
void loop() {
{
// cambia la direccion una vez que el motor alcanza la posicion objetivo
if (stepper.distanceToGo() == 0)
stepper.moveTo(-stepper.currentPosition());
stepper.run(); // MUST be called in loop() function
}
float temp = htu.readTemperature();
float hum = htu.readHumidity();
lcd.setCursor(8, 1);
lcd.print(hum);
lcd.setCursor(12, 0);
lcd.print(temp);
if (temp < 32) {
lcd.setCursor(15, 1);
lcd.print("*");
digitalWrite(6, 1);
} else {
digitalWrite(6, 0);
lcd.setCursor(15, 1);
lcd.print(" ");
}
}
Cuando lees el sensor de temperatura/humedad lo hace rápido? Cuanto demora entre lectura y lectura?
Acá hay un ejemplo que tiene un delay(500), si lo quitas cada cuanto presenta valores?
Acá tienes la respuesta
Según la hoja de datos del sensor tarda menos de 4 segundos en dar una lectura lo que se contradice con el ejemplo en el que pone un delay(500)
Fast response time < 4 sec.
De nuevo busqué otra hoja de datos y no habla de 4 sino de 5 y 8 segundos.
Cada lectura de temperatura y humedad tiene un delay de 50 mseg (ver código de la librería) entonces está agregando 100 ms de delay entre paso y paso *.
Te conviene leer la temperatura y la humedad solo cuando hace el cambio de sentido del motor.
Agrego:
(*) Y de acuerdo a la información que aporta @Surbyte la situación sería aún peor.
Confundí la respuesta a cambios climáticos. El sensor si hay un cambio de temperatura o de humedad demora 4 segundos que no es lo mismo que entregar la información 4 segundos despues. ERROR MIO!!
Tal vez así, haciendo lo que dice @MaximoEsfuerzo mejore la cosa
void loop() {
// Run the motor
if (stepper.distanceToGo() == 0) {
stepper.moveTo(-stepper.currentPosition()); // Change direction when target position is reached
// Read sensor only when the motor stops
float temp = htu.readTemperature();
float hum = htu.readHumidity();
// Update LCD
lcd.setCursor(8, 1);
lcd.print(hum);
lcd.setCursor(12, 0);
lcd.print(temp);
// Control based on temperature
if (temp < 32) {
lcd.setCursor(15, 1);
lcd.print("*");
digitalWrite(6, HIGH);
} else {
lcd.setCursor(15, 1);
lcd.print(" ");
digitalWrite(6, LOW);
}
}
stepper.run(); // Must be called continuously in the loop
}
Es fácil de deducir si ves el código de la librería
float Adafruit_HTU21DF::readTemperature(void) {
// OK lets ready!
uint8_t cmd = HTU21DF_READTEMP;
if (!i2c_dev->write(&cmd, 1)) {
return NAN;
}
delay(50); // add delay between request and actual read!
uint8_t buf[3];
if (!i2c_dev->read(buf, 3)) {
return NAN;
}
/* Read 16 bits of data, dropping the last two status bits. */
uint16_t t = buf[0];
t <<= 8;
t |= buf[1] & 0b11111100;
// 3rd byte is the CRC
float temp = t;
temp *= 175.72f;
temp /= 65536.0f;
temp -= 46.85f;
/* Track the value internally in case we need to access it later. */
_last_temp = temp;
return temp;
}
float Adafruit_HTU21DF::readHumidity(void) {
/* Prepare the I2C request. */
uint8_t cmd = HTU21DF_READHUM;
if (!i2c_dev->write(&cmd, 1)) {
return NAN;
}
/* Wait a bit for the conversion to complete. */
delay(50);
uint8_t buf[3];
if (!i2c_dev->read(buf, 3)) {
return NAN;
}
/* Read 16 bits of data, dropping the last two status bits. */
uint16_t h = buf[0];
h <<= 8;
h |= buf[1] & 0b11111100;
// 3rd byte is the CRC
float hum = h;
hum *= 125.0f;
hum /= 65536.0f;
hum -= 6.0f;
/* Track the value internally in case we need to access it later. */
_last_humidity = hum;
return hum;
}
Sumas 50 + 50 y ya tienes 100 mseg de retardo solo de base, sin siquiera sumar lo se demora en ejecutar el resto de las sentencias, de ahí viene la lentitud en los pasos.
Ya te dije que leas solo cada cambio de giro y @Surbyte te modificó el código de acuerdo a eso, o sea, ya lo tienes.
Además es completamente innecesario leer cada 103 mseg dos valores que cambian tan lentamente como la temperatura y la humedad, tranquilamente podrían leerse cada 1 minuto, o incluso más, sin inconvenientes.
Es verdad! No lo habia visto! Mala mia. @Surbyte Muchas gracias, está andando perfecto.
Si bien no es necesario leer la temperatura cada 103mseg tampoco se puede hacer a intervalos muy espaciados, ya que maneja un calefactor que si queda prendido mucho tiempo sin control, mata a los embriones por sobretemperatura.
Peeero... el paso a paso solo tiene que hacer media vuelta cada 6 horas nada mas. Y lo hace bastante rapido, asi que este evento solo se dara 4 veces al dia.