Arduino Cloud + Stepper moteur

Bonjour à tous,

Voilà je souhaite commander à distance (ESP8266) un moteur pas à pas (driver A4988) en continu, en fonction d'une température seuille réglable et transmise via mon dashboard.

Le problème est que lorsque le moteur fonctionne, celui ne fait que tourner, s’arrêter, tourner, s’arrêter.. comme si il subissait une interruption?

J'ai donc essayer de stocker les valeur dans l'eeprom en pensant que c’était lié au rafraichissement des variables mais j'ai toujours le meme probleme.

voici le code. Merci pour votre aide car je sèche un peu...

void loop() {
  
  ArduinoCloud.update();
  thermDigest();
  
  EEPROM.put(0, setTemp);
  EEPROM.commit();
  
  int setTemp2;
  EEPROM.get(0, setTemp2);
  
  Serial.print(" Set temperature(C) = ");
  Serial.println(setTemp2);
  
  EEPROM.put(4, temperature);
  EEPROM.commit();
  
  int temperature2;
  EEPROM.get(4, temperature2);
  
  Serial.print("Temp. Stockée = ");
  Serial.println(temperature2);
  
  if (temperature2 < setTemp2) {
 digitalWrite(LEDred, HIGH);
 digitalWrite(LEDgreen, LOW);
 etatChauffe = 1;
  
 }
 else {
 digitalWrite(LEDgreen, HIGH);
 digitalWrite(LEDred, LOW);
 etatChauffe = 0;
 } 

  EEPROM.put(8, etatChauffe);
  EEPROM.commit();
  
  int etatChauffe2;
  EEPROM.get(8, etatChauffe2);
  
  Serial.print("Etat Stocké = ");
  Serial.println(etatChauffe2);
 
  if (etatChauffe2 == 1){
  SteppMotorOn();
  }
  else {
  SteppMotorOff();
  }
  
  //delay(1000);
}

void onSetTempChange() {
  // Do something
}


void thermDigest(){

 currentTime=millis();
 if((currentTime-previousTime) > 30000){
 
 adc_value = analogRead(A0);
 Vout = (adc_value * VCC) / adc_resolution;
 Rth = (VCC * R2 / Vout) - R2;
  
 temp = (1 / (A + (B * log(Rth)) + (C * pow((log(Rth)),3))))-305;
 temperature = temp;
 
 //Serial.print("Temperature = ");
 //Serial.println(temperature);
 //Serial.println(" degree celsius");
 
 previousTime=currentTime;
  }
  
  
 }
  
void SteppMotorOn(){
  digitalWrite(DIR, HIGH);
  
  for(int i = 0; i<steps_per_rev; i++)
  {
  digitalWrite(STEP, HIGH);
  delayMicroseconds(2000);
  digitalWrite(STEP, LOW);
  delayMicroseconds(2000);
  }
} 
 
void SteppMotorOff(){
  digitalWrite(DIR, LOW);
  digitalWrite(STEP, LOW);
}

Bonjour

Attention, les ESP8266 ne contiennent pas de véritable EEPROM, la fonction EEPROM ici utilisée émule de l'EEPROM dans la mémoire FLASH . Cette dernière ne supporte que 100 000 écritures et un nombre infini de lectures.

De manière assez générale les microcontrolleurs 32 bits récents , pas seulement les ESP, ne contiennent pas d'EEPROM

On a eu récement sur le site le cas d'une personne qui écrivait en boucle en Flash et a détruit son ESP en moins de 24h

Merci al1fch,

Oui c'est ce que j'ai lu mais c'était juste pour vérifier si cette solution fonctionnait mais n'a pas vocation à perdurer.

la même logique 'provisoire' a grillé une mémoire Flash d'ESP en une nuit seulement......

merci mais la question de fond n'est pas celle ci dans mon sujet ...

En effet , mais il me me parait pas inutile d'attirer au passage l'attention sur un aspect non néglieable dont pourraient pâtir des lecteurs recopiant ton bout de code.

autre parenthèse : Arduino Cloud semble intéresser peu de monde ici , des solutions antérieures et concurrentes étant préférées.

On ne voit qu'une partie de ton code.
Mais en gros

  1. tu fais ArduinoCloud.update( )?? qui dure un certain temps (lequel??)
  2. tu regardes si 30 secondes se sont écoulées (auquel cas tu mesures la température)
  3. tu regardes si la température est inférieure à un seuil
    1. si oui, tu dis de chauffer et tu fais faire un tour au moteur
    2. si non, tu stoppes le moteur

Si on regarde ta loop(),

  • la mesure de la température ne se produit pas souvent et elle ne dure pas longtemps.
  • le test de la température par rapport au seuil ne dure pas longtemps

Donc la boucle devrait tourner assez vite et régulièrement.
Je vois 2 causes possibles à ton problème de "tourner, s’arrêter, tourner, s’arrêter" qui pourraient être:

  1. un temps important passé dans ArduinoCloud.update( )
  2. une bascule permanente de etatChauffe parce que tu es près du point de basculement de ton seuil.

Solutions proposées:

  1. pour la cause 1, chiffrer le temps passé dans ArduinoCloud.update( )
  2. pour la cause 2, introduire une hystérésis dans ta détermination du seuil pour que le basculement de etatChauffe soit franc.

1 remarques aussi tu mesures la température toutes les 30s mais tu appelles ArduinoCloud.update() en permanence est-ce bien nécessaire.

Merci pour ton retour fdufnews,

Oui j'ai mis 30 secondes pour eviter de mesurer tout le temps la température et avoir une certaine stabilité dans les mesures mais j'aurais pu faire une moyenne, ca aurait ete plus propre.

Le moteur tourne effectivement lorsque je chauffe, mais continuellement, pas seulement un tour. Et s'arrete lorsque je ne chauffe plus = température égale ou supérieure à la température réglée et transmise depuis ArduinoCloud.update() = Variable setTemp

Je pense effectivement que c'est ArduinoCloud.update() qui génère ces interruptions de la commande moteur "SteppMotorOn".

J'ai bien évidement écarter la problématique de température réglée trop proche de la température mesurée en réglant une température suffisamment éloignée..

Ci-dessous le code en entier nettoyé du stockage des variables pour éviter toute confusion dans le sujet :slight_smile:

#include "thingProperties.h"


unsigned long currentTime=0;
unsigned long previousTime=0;

// Temperature Sensor variables
int sensorPin = A0;      // Sets A0 as the input pin for the sensor
int sensorValue = 0;     // initialise a variable to store the value coming from thesensor

const double VCC = 3;             // NodeMCU on board 3.3v vcc
const double R2 = 10000;            // 10k ohm series resistor
const double adc_resolution = 1023; // 10-bit adc

const double A = 0.001129148;   // thermistor equation parameters
const double B = 0.000234125;
const double C = 0.0000000876741; 

float Vout, Rth, temp, adc_value; 


#define LEDred D1
#define LEDgreen D2


int STEP = 14; //GPIO14---D5 of Nodemcu--Step of stepper motor driver
int DIR  = 2; //GPIO2---D4 of Nodemcu--Direction of stepper motor driver

int etatChauffe = 0;
int etatChauffe1 = 0;
int etatMotor = 0;

const int  steps_per_rev = 200;

void setup() {
  
  Serial.begin(9600);
  delay(1500);
  
  EEPROM.begin(EEPROM_SIZE);
  
  pinMode(LEDred, OUTPUT);
  pinMode(LEDgreen, OUTPUT);
  
  pinMode(STEP, OUTPUT);
  pinMode(DIR, OUTPUT);
 
  while (!Serial);
  
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
 

}

void loop() {
  
  ArduinoCloud.update();
  thermDigest();
  
 if (temperature2 < setTemp) {
 digitalWrite(LEDred, HIGH);
 digitalWrite(LEDgreen, LOW);
 etatChauffe = 1;
  
 }
 else {
 digitalWrite(LEDgreen, HIGH);
 digitalWrite(LEDred, LOW);
 etatChauffe = 0;
 } 

  
  if (etatChauffe == 1){
  SteppMotorOn();
  }
  else {
  SteppMotorOff();
  }
  
  //delay(1000);
}

void onSetTempChange() {
  // Do something
}


void thermDigest(){

 currentTime=millis();
 if((currentTime-previousTime) > 30000){
 
 adc_value = analogRead(A0);
 Vout = (adc_value * VCC) / adc_resolution;
 Rth = (VCC * R2 / Vout) - R2;
  
 temp = (1 / (A + (B * log(Rth)) + (C * pow((log(Rth)),3))))-305;
 temperature = temp;
 
 //Serial.print("Temperature = ");
 //Serial.println(temperature);
 //Serial.println(" degree celsius");
 
 previousTime=currentTime;
  }
  
  
 }
  
void SteppMotorOn(){
  digitalWrite(DIR, HIGH);
  
  for(int i = 0; i<steps_per_rev; i++)
  {
  digitalWrite(STEP, HIGH);
  delayMicroseconds(2000);
  digitalWrite(STEP, LOW);
  delayMicroseconds(2000);
  }
} 
 
void SteppMotorOff(){
  digitalWrite(DIR, LOW);
  digitalWrite(STEP, LOW);
} 

Une solution simple pour que le moteur tourne sans interruption serait d'utiliser la fonction tone() pour générer le signal STEP.
A ce moment là,

  • SteppMotorOn() ferait un tone(STEP, 250);
  • SteppMotorOff() ferait notone(STEP);

Un tone ?

Et bien oui

tone génère une fréquence.
Lorsque tu fais

  digitalWrite(STEP, HIGH);
  delayMicroseconds(2000);
  digitalWrite(STEP, LOW);
  delayMicroseconds(2000);

tu génères un signal carré à 250Hz.
Donc tu peux aussi bien faire un tone(STEP, 250) qui va faire un signal carré à 250Hz aussi longtemps que tu ne feras pas noTone(STEP). Et donc le signal ne s'interrompra pas même pendant que tu feras ton ArduinoCloud.update();

Super, ça fonctionne. Merci :grinning:

De quelle solutions parle t on ? et plus intéressantes qu'arduino cloud ? Merci :roll_eyes: