Projet roue de géomètre - problème avec ATTINY 85

Bonjour à tous,

Je suppose que vous avez pour la plupart déjà vu un odomètre également appelé “roue de géomètre”. Si ce n’est pas le cas, ça ressemble à ça.

Comme j’ai récupéré un chouette mécanisme d’une machine à pain, je voulais m’en faire une version Arduino. Mon système est très simple : un simple interrupteur de fin de course (récupéré sur une imprimante) sert de compte-tours (il est en fait actionné 4 fois par tour, ce qui permet de gagner un peu en précision) et le microcontrôleur transmet la longueur cumulée à un module bluetooth HC05. J’utilise ensuite un terminal bluetooth sur mon smartphone pour lire la distance parcourue. Je n’aurai qu’à ajouter un interrupteur de reset et le tour sera joué.

J’ai testé ça sur Arduino Uno et ça marche très bien. Comme c’est assez basique et que je n’aime pas donner de la confiture aux cochons, j’ai alors voulu l’implémenter sur ATTINY85. C’est aussi pour moi l’occasion d’essayer cette puce : j’en ai acheté une dizaine il y a 3 ans et je n’en ai toujours rien fait…
J’utilise les pin 1 et 2 comme port série émulé et le pin 0 pour l’interrupteur (apparemment les Attiny ont des pull-up internes sur tous les ports).

Mon code est le suivant :

#include <SoftwareSerial.h>

SoftwareSerial mySerial(1, 2); // RX, TX

int compteur = 0;
int longueur = 0;

void setup(){
  
  mySerial.begin(9600);
  
  pinMode(0, INPUT_PULLUP);

}

void loop(){
  
  while (digitalRead(0) == HIGH) {
      } 
  while (digitalRead(0) == LOW) {
      } 
  compteur++;
  longueur = compteur * 0.11; // pour une roue de 14 cm et 4 interruptions par tour
  mySerial.println(compteur + " m");
  
}

Le hic est qu’avec l’ATTINY85, ça commence par fonctionner correctement puis rapidement je reçois sur le terminal bluetooth des suites de caractères bizarres et plus du tout les mesures. Je ne sais pas quel est le problème mais je me demande :

  • si la vitesse de transmission de 9600 bps est inadaptée
  • si la durée de traitement de la méthode println par l’attiny est supérieure à la durée pendant laquelle le pin 0 est haut (du coup la première commande de la boucle pourrait générer une erreur)

Pour info, j’ai volontairement évité d’utiliser attachInterrupt() parce que j’avais peur que ça ne fonctionne pas bien avec cette puce vu que ça ne marche que sur un certain nombre de pins de la UNO.

Auriez-vous un avis sur ce qui cloche ?

personne n'a d'idée ?

Bonjour,

Ca, ça fait n’importe quoi

 mySerial.println(compteur + " m");

Il faut faire deux print

 mySerial.print(compteur);
 mySerial.println(" m");

Merci Kamill c’était bien ça mais j’étais tellement persuadé que je pouvais faire une concaténation avec l’opérateur +…
Entre temps, je me suis acharné à reprendre mon programme avec une interruption externe mais pas moyen de faire fonctionner ça. J’en suis revenu à un programme moins élégant mais bien suffisant pour ce qu’il s’agit de faire. En fait, le seul truc dont je suis content est d’avoir eu l’idée d’un petit mécanisme qui, non seulement évite de casser l’interrupteur lorsque la roue fait marche arrière mais sert aussi à activer le reset du compteur.

Il faut faire deux print

mySerial.print(compteur);

mySerial.println(" m");

Ce n'est pas il faut, c'est on peut.
Avec Serial.println qui semble avoir la même syntaxe, et:

  • parce que je suis fénéantinformaticien et que c'est plus long d'écrire deux Serial.println qu'un seul
  • parce qu'il faut des print et un println à la fin et que par couper/coller je l'oublie et que je n'arrive plus à lire mes affichages qui se mélangent
  • parce que c'est plus simple de couper/coller une ligne plutôt que 2 (ou parfois plus)
  • parce que c'est plus simple d'effacer la ligne quand le bug s'est fait la malle
  • parce que la nature m'a donné la concaténation
    j'utilise la concaténation:
mySerial.println(String(compteur) + " m");

Ca m'arrive d'écrire:

void setup() 
{
  Serial.begin(115200);
  char x=12;
  int y=20;
  long z=25l;
    
  Serial.println("x="+String(byte(x))+"  y="+String(y)+"  z="+String(z));
}


void loop()
{
}

le String(byte(x)) c'est parce que le String(x) affiche le caractère "flèche" et pas le nombre

olivier_pecheux:
j'utilise la concaténation:

mySerial.println(String(compteur) + " m");

Tu as déjà essayé sur un attiny85?
Déjà que l'utilisation de String est (fortement) déconseillée sur une uno alors sur un attiny85 qui a encore moins de mémoire ...

Je suis plutôt de l'avis de kamill.

Je suis très sceptique quant aux conséquences de l'utilisation de String, qui implique une allocation dynamique, sur une cible ATTINY85 équipée de 512 octets de RAM.

Cela peut marcher un certain temps, mais sur le long terme cela provoquera forcément une fragmentation de la mémoire.
D'autre part, la quantité de code sera beaucoup plus importante (3626 octets (44%) contre 2316 octets (28%)), puisqu'il faudra inclure le code de String + le code de gestion du tas, et l'exécution sera plus lente.
Beaucoup d'inconvénients pour éviter d'écrire deux lignes au lieu d'une.

On peut d'ailleurs condenser en une seule :

mySerial.print(compteur);  mySerial.println(" m");

:wink:

Cela peut marcher un certain temps, mais sur le long terme cela provoquera forcément une fragmentation de la mémoire.

Effectivement, je le fais sur un Uno. Et pour la fragmentation, je m'en moque je n'utilise ça que pour le débogage.

Du coup, il vaudrait mieux utiliser
mySerial.print(compteur); mySerial.println(F(" m"));
Mais comme cela ne reste pas au final...