bonjour, je voudrais un peu d'aide car je suis dépassé par la modification du code que je voudrais réaliser.
je crée un ruban led qui forme un carré de 10m de coter et de 300led par coter soit 1200led sur 40m pour faire courir des personne a mobilité réduite et travaillé sur l'amélioration des prothèse.
j'ai repris un code qui s'appel "Neopixelrotatedloop" pour faire une incrémentation en vitesse de 2km/h a 14km/h de façon a ce que les cobaye suive la lumière au sol.
seulement je voudrais qu'il y ai trainé de lumière une par coté de façon a ce que 4 participant puisse courir en meme temps.
Voila mon code pour 1 trainé de lumière si on peut m'aider pour ajouter +3 trainé de lumière
(ps jutilise une arduino nano 33 ble)
#include <NeoPixelBus.h>
#include <NeoPixelAnimator.h>
#define Arduino_h
#include <math.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const uint16_t PixelCount = 1200; // make sure to set this to the number of pixels in your strip
const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
const uint16_t AnimCount = 1; // we only need one
const uint16_t TailLength = 5; // nombre de pixel allumer
const float MaxLightness = 0.3f; // max lightness at the head of the tail (0.5f is full bright)
int comptecycle; // compte le nombre de décalage pour arrivé a 1200 LED
int debut; // variable de temps 1
int fin; // variable de temps 2
float duree; // variable de Temps 2 moins temps 1
int vitesse = 0; // variable de la vitesse Fullspeed
int vitesse_s1 = 330; // variable de la vitesse 1
int vitesse_s2 = 162; // variable de la vitesse 2
int vitesse_s3 = 107; // variable de la vitesse 3
int vitesse_s4 = 79; // variable de la vitesse 4
int vitesse_s5 = 62; // variable de la vitesse 5
int vitesse_s6 = 50; // variable de la vitesse 6
int vitesse_s7 = 43; // variable de la vitesse 7
int vitesse_s8 = 20; // variable de la vitesse 8
int color = 1;
int timer; // variable qui prend vitesse_x et qui fait fluctuer la vitesse
float calculvitesse; // variable pour avoir la vitesse en m/s
float kmh; // variable pour avoir la vitesse en km/h
float longled = 40; // longeur de la course
float conver = 3.6; // variable de conversion de m/s en km/h
NeoGamma<NeoGammaTableMethod> colorGamma; // for any fade animations, best to correct gamma
NeoPixelBus<NeoGrbFeature, NeoWs2812xMethod> strip(PixelCount, PixelPin);
// for esp8266 omit the pin
//NeoPixelBus<NeoGrbFeature, NeoWs2812xMethod> strip(PixelCount);
NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object
void SetRandomSeed()
{
uint32_t seed;
// random works best with a seed that can use 31 bits
// analogRead on a unconnected pin tends toward less than four bits
seed = analogRead(0);
delay(1);
for (int shifts = 3; shifts < 31; shifts += 3)
{
seed = analogRead(0) << shifts;
delay(1);
}
// Serial.println(seed);
randomSeed(seed);
}
void LoopAnimUpdate(const AnimationParam& param)
{
// wait for this animation to complete,
// we are using it as a timer of sorts
if (param.state == AnimationState_Completed)
{
// done, time to restart this position tracking animation/timer
animations.RestartAnimation(param.index);
// rotate the complete strip one pixel to the right on every update
strip.RotateRight(5); // decalage de 5 LED par 5 led
}
}
void DrawTailPixels()
{
// using Hsl as it makes it easy to pick from similiar saturated colors
float hue = color; //couleur des led
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
}
void setup()
{
Serial.begin(9600);
strip.Begin();
strip.Show();
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.display();
//delay(2000); // Pause for 2 seconds
SetRandomSeed();
// Draw the tail that will be rotated through all the rest of the pixels
DrawTailPixels();
// we use the index 0 animation to time how often we rotate all the pixels
animations.StartAnimation(0, 1, LoopAnimUpdate);
//animations.StartAnimation(1, 300, LoopAnimUpdate);
comptecycle = 0;
timer = vitesse;
}
void loop()
{
animations.UpdateAnimations();
strip.Show();
if (comptecycle < 239)
{
if (comptecycle == 0)
{
debut = millis();
timer = vitesse_s1 ;
//Serial.println("Segment 1");
//delay(3000);
}
if (comptecycle == 30)
{
timer = vitesse_s2;
//Serial.println("Segment 2");
//delay(3000);
}
if (comptecycle == 60)
{
timer = vitesse_s3;
//Serial.println("Segment 3");
//delay(3000);
}
if (comptecycle == 90)
{
timer = vitesse_s4;
//Serial.println("Segment 4");
//delay(3000);
}
if (comptecycle == 120)
{
timer = vitesse_s5;
//Serial.println("Segment 5");
//delay(3000);
}
if (comptecycle == 150)
{
timer = vitesse_s6;
//Serial.println("Segment 6");
//delay(3000);
}
if (comptecycle == 180)
{
timer = vitesse_s7;
//Serial.println("Segment 7");
//delay(3000);
}
if (comptecycle == 210)
{
timer = vitesse_s8;
//Serial.println("Segment 8");
//delay(3000);
}
//Serial.print("cycle : ");
//Serial.println(comptecycle);
comptecycle++;
} else {
fin = millis();
comptecycle = 0;
Serial.println("************ AFFICHAGE DES TEMPS ************");
Serial.println(" ********************* ");
Serial.println("***********************************************");
duree = fin - debut;
Serial.println("");
Serial.print("Temps d'une boucle : ");
Serial.print(duree);
Serial.println("ms");
duree = duree / 1000 ;
Serial.println("");
Serial.print("Temps d'une boucle : ");
Serial.print(duree);
Serial.println("S");
Serial.println("");
calculvitesse = longled / duree ;
Serial.print(" vitesse en m/s : ");
Serial.print(calculvitesse);
Serial.println("m/s");
Serial.println("");
kmh = calculvitesse * conver;
Serial.print(" vitesse en km/h : ");
Serial.print(kmh);
Serial.println(" km/h");
Serial.println("");
Serial.println("");
Serial.println("************ FIN DE L'AFFICHAGE ************");
Serial.println(" ********************* ");
Serial.println("***********************************************");
Serial.println("");
Serial.println("");
Serial.println("");
//Serial.println("***********************************************");
//Serial.println("***********************************************");
//Serial.println("***********************************************");
display.clearDisplay();
display.setTextSize(1); // taille du texte
display.setTextColor(WHITE);
display.setCursor(0, 0); // position du curseur colonne / ligne
display.print(" vitesse moyenne : ");
display.println();
display.print(duree);
display.println();
display.display();
delay(3000);
}
delay(timer);
}
Pendant ces 0,36s il aura fallu rafraichir 30 fois le bandeau lumineux puisque vous avez 30 leds par mètre
donc il faut rafraîchir le bandeau toutes les 12ms (0.36 / 30 = 0,012s)
hors, il faut 30 micro-secondes pour mettre à jour un Neopixel. Avec 1200 Leds, l'affichage du bandeau prend ~36ms
Il faut bien sûr compter un peu de temps de calcul pour faire avancer les différents flux lumineux sur le bandeau ➜ vous ne pourrez pas gérer 10 km/h - au mieux ce sera entre 2 et 3km/h sans doute
Il faudrait passer sur des bandeaux type APA102 (ce que Adafruit appelle DotStar) qui sont beaucoup plus rapides que les Neopixels.
voici un exemple sinon de code relativement simple pour faire "se courir après N pistes (N est défini par la valeur de nbPistes) dont la longueur de traîne est définie par la variable longueurTraine (ici 5 pixels)
(la simulation est assez lente et je n'ai que 200 Neopixels)
le code
#include <Adafruit_NeoPixel.h>
const byte brocheStrip = 5;
const uint16_t nbLeds = 200;
Adafruit_NeoPixel strip(nbLeds, brocheStrip, NEO_GRB + NEO_KHZ800);
const byte nbPistes = 4;
uint16_t position[nbPistes];
const byte longueurTraine = 5;
unsigned long deltaT = 30; // nombre de ms entre 2 décalages
uint16_t teintePiste[nbPistes];
void affichePistes() {
static unsigned long dernierMillis = -deltaT;
if (millis() - dernierMillis >= deltaT) {
for (byte piste = 0; piste < nbPistes; piste++) {
strip.setPixelColor(position[piste], Adafruit_NeoPixel::ColorHSV(teintePiste[piste], 255, 255)); // on affiche le point de tête
// on dessine la traîne
for (uint16_t i = 1; i <= longueurTraine; i++) {
uint16_t pos = (position[piste] + nbLeds - i) % nbLeds;
strip.setPixelColor(pos, Adafruit_NeoPixel::ColorHSV(teintePiste[piste], 255, map(i, -1, longueurTraine, 255, 0))); // on affiche le point de tête
}
position[piste] = (position[piste] + 1) % nbLeds; // on avance d'un pixel pour la prochaine fois
}
strip.show();
for (uint16_t i = 0; i < nbLeds; i++) strip.setPixelColor(i, 0); // on pré-efface pour la prochaine fois
dernierMillis = millis();
}
}
void setup() {
for (byte piste = 0; piste < nbPistes; piste++) {
position[piste] = piste * (nbLeds / nbPistes); // positions initiales
teintePiste[piste] = piste * (0xFFFFu / nbPistes); // répartition de différentes teintes
}
Serial.begin(115200);
strip.begin();
}
void loop() {
affichePistes();
}
actuellement j'arrive a faire 8 vitesse pour une trainé lumineuse et 1200 led en jouant sur le delay dans la fonction loop :
1/ 0.5m/s
2/ 1m/s
3 / 1.5 m/s
4/ 2 m/s
5/ 2.5m/s
6/ 3m/s
7/ 3.5m/s
8/ 4m/s
vitesse mesuré au chrono et avec la fonction millis
J'aurai souhaité allumer 4 trainé lumineuse au lieu de 1 mais il y a un risque de perte de vitesse.
j'ai pensé commandé "4" segment de 10m en parallèle au lieu de les commander en série mais ca m'oblige a rajouter un câble pour commander chaque entrée de segment de 10 .
(ajout)
je viens de testé la solution du câble en parallèle et ca marche mais c'est lourd niveau connexion
j'instrumente 300 led au lieu de 1200 en //
non, le code met à jour toute la bande lumineuse. que le pixel soit noir ou vert ça ne change rien il faut envoyer quand même des données.
bien sûr il faudra un peu de temps pour calculer les couleurs des pixels des autres trainées, mais ce n'est pas ce qui est le plus couteux
Le bandeau mets 36ms pour s'afficher, en supposant que le reste du temps de calcul pour définir le contenu du bandeau soit négligeable, vous pouvez faire avancer d'un pixel toute les 36ms.
Vous avez 30 pixels par mètres, donc 3.33cm entre deux pixels, donc vous avancez au mieux de 3.33cm toutes les 36ms si vous allumez pixel par pixel.
V = D / T = (3,33/100/1000) / (0,036 / 3600000) = 3.33 km/h
je n'ai pas regardé le code en détail car il utilise des bibliothèques mais si tous les pixels s'allument un par un, vous ne pourrez pas dépasser 3.33km/h
Si ça va plus vite, c'est que la bibliothèque saute des pixels - ce qui dans l'absolu est envisageable
je te fait une vidéo c'est plus parlant !
et je tien a te dire que je comprend ton calcul qui semble logique .... et implacable !
et effectivement j'avance 5 pixel par 5 pixel ,
// rotate the complete strip one pixel to the right on every update
strip.RotateRight(5);
(plus pratique pour compter les cycle) il y a dans mon code un compteur qui incrémente la vitesse en fonction de la position sachant qu'il faut 30 cycle pour faire 150 led ce qui équivaut a la taille d'un bandeau
ex:
0 a 30 0.5ms
31 à 60 1m/s
61à 90 1.5m/s
ect...
je n'ai pas obtenue ces vitesses avec mon code qui tourné avec la boucle for à 3km/h max comme tu le disait avant j'ai utilisé la librairie "neopixel" avec le code exemple que j'ai modifier et donné plus haut ca donne ce que tu voies.
j'ai bien 4m/s sur le dernier cycle
il y a un problème de masse que je vais résoudre (d'où la couleur bleu) mais meme en série j'ai les meme vitesse
video 1200 led série :
vitesse : 4/m/s 10s pour un tour de 40m
ce que je voulais savoir c'est comment affiché 4 bandeau lumineux symétrique un par coter qui on une avance similaire en gardant la liaison en série et non en parallèle comme sur la première vidéo car sur la première video jai relié les 4 entrée de commande en // ce qui donne la meme chose mais oblige a avoir un cable qui circule le long des led
en théorie la pratique et la théorie devraient donner le même résultat mais parfois en pratique ça n'est pas le cas
faut comprendre pourquoi :
j'ai regardé d'un peu plus près votre code et vous n'utilisez pas la bibliothèque Adafruit_NeoPixel mais NeoPixelBus mais ça ne change rien à la contrainte de temps qui est inhérente au type de LEDs utilisées
Je ne connaissais pas la biblio NeoPixelAnimator mais j'ai regardé un peu le code et un commentaire dans votre code ne correspond pas à la réalité
vous ne décalez pas de 1 pixel ver la droite mais de 5 entre 2 étapes ➜ donc oui vous pourrez alors théoriquement monter jusqu'à 5 * 3.33 ~16 km/h mais il ne faut pas négliger non plus le temps de calcul pour ce décalage.
pour avoir vos 4 petits bandeaux qui se déplacent : la fonction d'animation a la bonne idée de décaler ce qui existe déjà sur le bandeau, donc à priori si on dessine au début les 4 trainées, ensuite elle se déplaceront
dans le setup() vous avez un appel à DrawTailPixels(); qui en dessine une. il vous suffirait de répéter 4 fois la boucle for mais en ne prenant pas l'index 0 comme premier point à chaque fois mais en décalant ➜ 0, 300, 600, 900
void DrawTailPixels()
{
// using Hsl as it makes it easy to pick from similiar saturated colors
float hue = color; //couleur des led
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
for (uint16_t index = 300; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
for (uint16_t index = 600; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
for (uint16_t index = 900; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
}
Non il n'y a qu'une seule animation qui fait tourner TOUS les pixels du bandeau, les noirs comme ceux qui sont allumés mais dans le rendu bien sûr on ne voit pas que ceux qui étaient éteint ont bougé s'ils restent éteints.
c'est dans DrawTailPixels qu'il faut faire la modif
vous avez cette boucle
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
qui dit "allume les pixels de 0 à TailLength avec la couleur calculée" ➜ c'est ça qui vous fait un bandeau
si vous faisiez
for (uint16_t index = 300; index < strip.PixelCount() && index <= 300+TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
alors vous auriez allumé les pixels depuis la position 300
donc je serais tenté de faire
void DrawTailPixels()
{
for (uint16_t pos = 0; pos <= 900; pos += 300) { // pour pos qui prend les valeurs 0 300 600 900
// using Hsl as it makes it easy to pick from similiar saturated colors
float hue = color; //couleur des led
for (uint16_t index = pos; index < strip.PixelCount() && index <= pos+TailLength; index++) {
float lightness = (index-pos) * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
}
}
ca marche mais je comprend moyen ton code et ca c'est car car je suis moins fort que toi.
je le commente pour que tu me dise si ma compréhension est bonne.
void DrawTailPixels()
{
for (uint16_t pos = 0; pos <= 900; pos += 300) //déclare position 0 et tant que position est inferieur ou égale à 900 position fait +300
{
float hue = color; // defini la couleur des pixel
for (uint16_t index = pos; index < strip.PixelCount() && index <= pos+TailLength; index++) //index prend pos tant que index et inferrieur ou égale à la fonction pixelcount et index est inferrieurou égale à la position +la taille de la trainé je fait incrementaion de index +1
{
float lightness = (index-pos) * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
}
}