Probleme Incompréhensible :/ Sisi je vous jure !

Bonjour :slight_smile:

Alors voila j’ai un petit problème et je ne comprends absolument d’où il vient, je ne crois pas trouver la solution ici mais après avoir tout essayé pendant des heures, je me dis que ce n’est pas une si mauvaise idée ^^

Donc si vous voulez bien m’accorder quelque minute d’attention, Voici mon probleme :

Je suis actuellement en train de dev un system de laser tag, jusque là rien d’impressionnant, pour se faire j’utilise un laser ^^ et de l’autre coté une cellule solaire et je fais passer les info en binaire en modifiant les temps down entre chaque pic … :confused: bon en gros |||||||___ vaut 0 1 0 1 1 0

Et puisque le system doit pouvoir recevoir du signal depuis plusieurs cellules ainsi que de pourvoir envoyer/recevoir en même temps => interdit d’utiliser des delay, seulement des system basé sur des timers, encore une fois jusque la facile …

Sauf que voila je ne sais pas pourquoi en testant mon débit j’ai qq chose d’incompréhensible, une partie du code (inutile en temps normal) change complétement mon débit (le divise par 2). Donc si je retire ce bout de code mon debit chute Mais si je le bloque (condition if impossible) le débit reviens a la normale :confused:

Voici mon code (désoler un peu bordélique ^^)

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 6, NEO_GRB + NEO_KHZ800);

uint32_t color = strip.Color(255, 0, 0);

void setup() 
{
  pinMode(2, INPUT);
  pinMode(4, OUTPUT);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  strip.setBrightness(20);

  colorWipe(color, 50);
}

unsigned long LastTimer = micros();
int InputBits = 0;
int Count = 0;
int timed = 100;

byte Data[8] = {0, 1, 0, 0, 1, 1, 0, 1};

bool Received = false;

void loop()
{
  if (Received)
  {
    colorWipe(strip.Color(0, 0, 0), 0);
    delay(300);
    colorWipe(color, 0);
    delay(300);
    colorWipe(strip.Color(0, 0, 0), 0);
    delay(300);
    colorWipe(color, 0);
    delay(300);
    colorWipe(strip.Color(0, 0, 0), 0);
    delay(300);
    colorWipe(color, 0);
    delay(300);
    colorWipe(strip.Color(0, 0, 0), 0);
    delay(2000);
    
    Received = false;

    colorWipe(color, 50);
  }
  else
  {
    GetBits();
  }
}

int LowCount = 0;
int HighCount = 0;
String BitInsput = "";
String Identifier = "0100110110110010"; //

int ReceivedCount = 0;
unsigned long StartCount = 0;

int testcount = 0;

void GetBits()
{
  unsigned long StartTimer = micros();
  unsigned long Delta = StartTimer - LastTimer;

  if (Delta >= timed)
  {
    if (digitalRead(2) == HIGH)
    {
      if (LowCount == 1)
      {
        BitInsput += "0";
      }
      else
      if (LowCount == 2)
      {
        BitInsput += "1";
      }

      if (BitInsput.endsWith(Identifier))
      {

        testcount++;

        if(testcount == 200)
        {
          Received = true;
        }
        
        ReceivedCount = 0;
        BitInsput = "";

        if(ReceivedCount == 200)
        {
          int diff = millis() - StartCount;
          Serial.println("Done !");
          Serial.println("In " + String(diff) + " msec");
          Serial.print(200 / (float(diff) / 1000));
          Serial.println(" Octets/sec");
          Serial.println("Delta = " + String(Delta));

          ReceivedCount = 0;
          StartCount = millis();
        }
      }
      else
      if (BitInsput.length() > 32)
      {
        BitInsput = "";
      }

      LowCount = 0;
    }
    else
    {
      LowCount++;
    }

    LastTimer =  StartTimer;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

Donc en gros je test tout les 50 microseconde l’état du signal et je cumule les niveaux bas :
1 niveau bas = 0
2 niveaux bas successif = 1

Et donc la portion de code qui pose problème :

if(ReceivedCount == 200)
        {
          int diff = millis() - StartCount;
          Serial.println("Done !");
          Serial.println("In " + String(diff) + " msec");
          Serial.print(200 / (float(diff) / 1000));
          Serial.println(" Octets/sec");
          Serial.println("Delta = " + String(Delta));

          ReceivedCount = 0;
          StartCount = millis();
        }

(Je vous rassure mon code final ne ressemble pas a ça mais dans ce code qui fonctionne un peu différemment le même phénomène se produit)

Si vous ne voyez rien ce n’est pas trop grave car ça fonctionne comme même, c juste emmerdant de perde du débit comme ça sans comprendre :confused:

Merci :smiley:

Serial.print() fonctionne sous interruption en émission comme en réception elle dispose d'un buffer de 64 caractères. Lorsque la chaîne à envoyer dépasse la capacité du buffer Serial devient bloquant en attendant de la place dans le buffer. Tu émets à 9600 bauds soit environ 1 caractère par milliseconde. C'est pas bien rapide.

Les Serial.print() pour la mise au point c'est bien mais il ne faut pas qu'ils soient intrusifs. Donc, limiter la longueur des messages au strict nécessaire et utiliser de préférence un débit élevé (115200 par exemple).

bonjour, +1 tu peux aussi modifier la lib pour la passer de 64 à 128 caractères

Rien de plus à ajouter si ce n'est pour insister sur le fait que Serial.print utilise l'UART et l'UART est matérielle. C'est a dire qu'une fois lancé le matériel fonctionne parrallelement et indépendement du programme et donc le traitement (interuption et fin de traitement entre autres) n'est pas controlé par le programme et peut se produire a n'importe quel moment d'où une source de conflit si la boucle qui appelle le serialprint est trop rapide. D'où l'interet d'utiliser le débit max. IDE arduino.cc ( 1.6.5 ) débit max 250 kHz. IDE arduino.org ( 1.7.8 ) débit max 115,200 kHz.

Je me suis fait avoir une fois. Pour tout ces problème de temps un analyseur logique à 7€ (clone de saleae) est idéal.

D’abord merci a vous, ensuite quand je parle de "débit" c'est bien le débit de donnée laser, pas celui du serial. Mais soit j'ai compris (enfin je crois) le prob, apparemment le code réglait, sans que ce ne soit voulu, un problème de synchro. Donc maintenant ça fonctionne nickel (après réécriture du code de send coter laser)