Des calculs fous !

Bonjour tout le monde !
Je suis un ptit nouveau sur le forum arduino, mais cela fait plus d'un an que j'utilise une arduino.
J'ai récemment acheté une carte arduino-like : La Romeo de DFRobot pour me monter un robot-monster-truck pilotable via une liaison série sans fil.

Le problème, c'est que j'obtient des résultats absolument délirants pour une calcul tout bête, et je ne sais pas d'ou celà peut provenir. Je vous explique un peu :
Du côté ordinateur, processing envoie des trames du style "20m" et la carte l'interprete comme envoyer 20 / 255 au moteur (en PWM).
Sauf que pour limiter la vitesse (car le joystick que j'utlise est très sensible), j'ai mis un diviseur. Par exemple si l'arduino reçoit "20m" avec un diviseur de 4 réglé au préalable, je suis censé envoyer 5 au moteur sur le PWM.
Sauf que la carte me calcule des trucs totalement délirants, genre -3667 ou autre...
Pourtant la section ne m'apparait pas fausse, qu'en dites-vous :

case 'm': 
      motorvalue = int(v) / motordivider;
      analogWrite(motorpin, motorvalue); 
      Serial.println(motorvalue);
      break;

Comme vous pouvez le remarquer, je me suis inspiré de l'exemple SingleServo pour l'adapter un peu.

Est-ce que vous avez une idée de ce qui pourrais clocher ?
Bonne journée à tous,
Valentin. :slight_smile:

Bonjour,

imval:
Le problème, c'est que j'obtient des résultats absolument délirants pour une calcul tout bête, et je ne sais pas d'ou celà peut provenir. Je vous explique un peu :
Du côté ordinateur, processing envoie des trames du style "20m" et la carte l'interprete comme envoyer 20 / 255 au moteur (en PWM).
Sauf que pour limiter la vitesse (car le joystick que j'utlise est très sensible), j'ai mis un diviseur. Par exemple si l'arduino reçoit "20m" avec un diviseur de 4 réglé au préalable, je suis censé envoyer 5 au moteur sur le PWM.
Sauf que la carte me calcule des trucs totalement délirants, genre -3667 ou autre...
Pourtant la section ne m'apparait pas fausse, qu'en dites-vous :

case 'm': 

motorvalue = int(v) / motordivider;
      analogWrite(motorpin, motorvalue);
      Serial.println(motorvalue);
      break;

Sans le code complet c'est impossible de voir ou ce situe le probléme, si tu obtient des nombres négatif c'est surement que tu a dépasser la limite du type de la variable en question.

case 'm': 
  {
    motorvalue = (int)v / motordivider; // attention au possible erreur de virgules lors de la conversion en int 
    analogWrite(motorpin, motorvalue); // motorvalue doit être de type byte ou de type int
    Serial.println(motorvalue, DEC); 
  } 
  break;

Voici les morceaux de code qui sont en rapport avec :

const int motorpin = 11;

int motorvalue = 0;
int motordivider = 4;
void loop()
{

  static int v = 0;
  
  if ( Serial.available()) {
    char ch = Serial.read(); 

    switch(ch) {
      
    case '0'...'9':
      v = v * 10 + ch - '0';
      break;

      case 'c': 
      motordivider = 4; 
      myLCD.setCursor(14, 1); 
      myLCD.print("/4"); 
      break;
    case 'v': 
      motordivider = 2; 
      myLCD.setCursor(14, 1); 
      myLCD.print("/2"); 
      break;
    case 'm': 
      motorvalue = int(v) / motordivider;
     if(motorvalue <= 254 && motorvalue >= 0) {
      analogWrite(motorpin, motorvalue); 
      myLCD.setCursor(0,0); 
      myLCD.print("Motor:          ");
      myLCD.setCursor(7,0);
      myLCD.print(motorvalue);
      //Serial.println(motorvalue);
     }
      break;
      
    }
  }

}

case '0'...'9':

C'est un raccourci pour nous expliquer ce que fait ton programme??
Sinon cette syntaxe n'est pas autorisée en C. On doit mette tous les cas.

    case '1'':
    case '2':
    case '3'':
    case '4'':                   // et ainsi de suite jusqu'à 9
      v = v * 10 + ch - '0';
      break;

Ce morceau de code (le case '0' ... '9': ) fonctionne parfaitement, j'ai testé avec ta méthode, et aucun changement. C'est un raccourcis et il est même donné sur http://www.arduino.cc/playground/Learning/SingleServoExample

Par contre, j'obtient toujours des valeurs totalement improbables :confused: Et mes variables ont l'air correctes.

Voilà le code complet du robot (pas encore terminé) :

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Servo.h>

LiquidCrystal_I2C myLCD(0x27,16,2);

Servo servo1; 
Servo servo2; 
Servo servo3; 
Servo servo4;

const int tonepin = 2;
const int ledpin = 12;
const int motorpin = 11;

int lastclear = 0;
int motorvalue = 0;
int motordivider = 4;

bool sens = HIGH;
bool ledstate = LOW;

void setup()
{

  pinMode(ledpin, OUTPUT);
  pinMode(motorpin, OUTPUT);

  digitalWrite(motorpin, LOW);
  digitalWrite(ledpin, LOW);

  servo1.attach(4);
  servo1.write(90);

  servo2.attach(5);
  servo2.write(90);

  servo3.attach(6);
  servo3.write(90);

  servo4.attach(7);
  servo4.write(90);

  Serial.begin(9600);
  Serial.println("Ready Robot E-Savage");

  tone(tonepin, 1000, 200);
  myLCD.init();
  myLCD.backlight();
  myLCD.print(" Robot E-Savage");
  myLCD.setCursor(0, 1);
  myLCD.print("     imval");
  delay(1000);
  myLCD.clear();
  tone(tonepin, 600, 200);

}

void loop()
{
  
/*    if((millis() - lastclear) > 1000) { 
    myLCD.clear(); 
    lastclear = millis(); 
  }*/

  static int v = 0;
  
  if ( Serial.available()) {
    char ch = Serial.read(); 

    switch(ch) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      v = v * 10 + ch - '0';
      break;
      
    case 'l':
      ledstate = !ledstate;
      digitalWrite(ledpin, ledstate);
      break;
    case 's':
      servo1.write(v);
      v = 0;
      break;
    case 'w':
      servo2.write(v);
      v = 0;
      break;
    case 'x':
      servo3.write(v);
      v = 0;
      break;
    case 'y':
      servo4.write(v);
      v = 0;
      break;
      
      case 'c': 
      motordivider = 4; 
      myLCD.setCursor(14, 1); 
      myLCD.print("/4"); 
      break;
    case 'v': 
      motordivider = 2; 
      myLCD.setCursor(14, 1); 
      myLCD.print("/2"); 
      break;
    case 'b': 
      motordivider = 1; 
      myLCD.setCursor(14, 1); 
      myLCD.print("/1"); 
      break;
    case 'm': 
      motorvalue = int(v / motordivider);
     if(motorvalue <= 254 && motorvalue >= 0) {
      analogWrite(motorpin, motorvalue); 
      myLCD.setCursor(0,0); 
      myLCD.print("Motor:          ");
      myLCD.setCursor(7,0);
      myLCD.print(motorvalue);
      //Serial.println(motorvalue);
     }
      break;
      
    }
  }

}

Bonjour,

cette ligne m'interpelle :

motorvalue = int(v / motordivider);

En effet, que cherches-tu à faire ? à t'assurer que le résultat soit bien un entier ?

Si c'est le cas, la "bonne" écriture serait ceci :

motorvalue = (int)(v / motordivider);

Cependant, pourquoi effectues-tu un cast en INT sur une division d'un INT par un INT ? Car le résultat sera toujours un INT, donc ton cast est inutile.
Et, je dirais même plus, étrange car ensuite, tu effectues une comparaison étrange :

      if(motorvalue <= 254 && motorvalue >= 0)

Que cherches-tu à faire avec cette comparaison ?
motorvalue étant déclaré comme un int (entier positif et négatif), pourquoi comparer cette plage qui correspondrai au domaine d'un CHAR ?


Stéphane