Arduino и световые эффекты

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Добрый день. Суть вопроса такова: делаю беспроводной контроллер световых эффектов на NRF24L01.

Все работает отлично, но вот когда выбираются программы эфектов, то через некоторое время loop зависает и arduino иногда перегружается. Думал может дело в переполнении памяти, но вроде все норм.

Вот код

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
const byte dim_curve[] = {
    0,   1,   1,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,
    3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,   4,
    4,   4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,
    6,   6,   6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
    8,   8,   9,   9,   9,   9,   9,   9,   10,  10,  10,  10,  10,  11,  11,  11,
    11,  11,  12,  12,  12,  12,  12,  13,  13,  13,  13,  14,  14,  14,  14,  15,
    15,  15,  16,  16,  16,  16,  17,  17,  17,  18,  18,  18,  19,  19,  19,  20,
    20,  20,  21,  21,  22,  22,  22,  23,  23,  24,  24,  25,  25,  25,  26,  26,
    27,  27,  28,  28,  29,  29,  30,  30,  31,  32,  32,  33,  33,  34,  35,  35,
    36,  36,  37,  38,  38,  39,  40,  40,  41,  42,  43,  43,  44,  45,  46,  47,
    48,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
    63,  64,  65,  66,  68,  69,  70,  71,  73,  74,  75,  76,  78,  79,  81,  82,
    83,  85,  86,  88,  90,  91,  93,  94,  96,  98,  99,  101, 103, 105, 107, 109,
    110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
    146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
    193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};

typedef struct
{          
 byte  d1; // number device
 int   d2; // vbat
 float d3; // temp
 float d4; // -
 byte  d5; // -
 byte  d6; // -
 byte  d7; // -
 byte  d8; // -
 byte  d9; // -
}
B_t;
B_t data;
 
RF24 radio(7,8);   // make sure this corresponds to the pins you are using
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int ledPinR=6;
int ledPinG=10;
int ledPinB=5;
int ledPinW=9;
int mode=0;
int r, g, b;

int rgb_colors[3]; 
int fadeSpeed = 2; // 'speed' of fading
int saturation =255;

unsigned int rgbColour[3];
long previousMillis = 0;  
//---------- -----------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println("Start");
  radio.begin();
  radio.openReadingPipe(1,pipes[1]);
  radio.startListening();
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinG, OUTPUT);  
  pinMode(ledPinB, OUTPUT);
  pinMode(ledPinW, OUTPUT);
  prog3();        
}
//---------- ----------------------------------------- 
void loop()
{ 
 unsigned long currentMillis = millis();
 if(currentMillis - previousMillis > 1000)
  {
   previousMillis = currentMillis;
//    Serial.print("Mode=");
//    Serial.println(mode);  
  } 
 read_rf();
 prog1();// strobe
//  } 
// else if (mode==2)
//  {
//   prog2();// ambient
//  } 
// else if (mode==3)
//  {
//   prog3();// all clear
//  } 
// else if (mode==4)
//  {
//   prog4(); // fade
//  }
}
//---------------------------------------------------
//-------------------------------------------------------
void read_rf()
{
 if ( radio.available() )
  {
   bool done = false;
   while (!done)
    {
     done = radio.read( &data, sizeof(data) );
     Serial.println("new data");
     Serial.println(int (data.d5)); //r
     Serial.println(int (data.d6)); //g
     Serial.println(int (data.d7)); //b
     Serial.println(int (data.d9)); //mode

     if (data.d1==16) 
       {
         if (data.d9==0) //mode set rgb colorwhel
          {
           analogWrite(ledPinR, data.d5);      
           analogWrite(ledPinG, data.d6);          
           analogWrite(ledPinB, data.d7);
           mode=0;
          }
         else if (data.d9!=0)
          {
           mode=data.d9;
          } 
       }
   }
 }  
}
//--------------------------------------------------------------------------------------------------
void prog4()
{
  for (int decColour = 0; decColour < 3; decColour += 1)
  {
    int incColour = decColour == 2 ? 0 : decColour + 1;
    for(int i = 0; i < 255; i += 1)
    {
      rgbColour[decColour] -= 1;
      rgbColour[incColour] += 1;
      setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
      delay(20);
    }
  }  
}
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(ledPinR, red);
  analogWrite(ledPinG, green);
  analogWrite(ledPinB, blue);
 }
//---------- -----------------------------------------
void prog2()
{
int hue = random(0, 360);

 for(int brightness=0;brightness<255;brightness++)
   {
    brightness = brightness + fadeSpeed;            // change fadeVal by speed
    getRGB(hue,saturation,brightness,rgb_colors);   // converts HSB to RGB
    delay(5); // delay to slow down fading
   }
 for(int brightness=255;brightness>0;brightness--)
   {
    brightness = brightness - fadeSpeed;         // change fadeVal by speed
    getRGB(hue,saturation,brightness,rgb_colors);   // converts HSB to RGB
    delay(5); // delay to slow down fading
   }
 delay(1000);  
}
//---------- -----------------------------------------
void prog3()// all off
{
 analogWrite(ledPinR, 0);
 analogWrite(ledPinG, 0);
 analogWrite(ledPinB, 0);
// mode=99; 
}
//-------------------------------------------------------
void prog1()
{
 if (mode==1)
 {
  r=random(0,255);
  g=random(0,255);
  b=random(0,255);
  cop_flash();
  delay (100);
  cop_flash();
  delay (100);
  cop_flash();
  delay (1000);
 }
} 
//---------- -----------------------------------------
void cop_flash()
{
  analogWrite(ledPinR, r);
  analogWrite(ledPinG, g);
  analogWrite(ledPinB, b);
  delay(10);
  analogWrite(ledPinR, 0);
  analogWrite(ledPinG, 0);
  analogWrite(ledPinB, 0);
}
//----------------------------------------------------
void getRGB(int hue, int sat, int val, int colors[3])
{ 
  val = dim_curve[val];
  sat = 255-dim_curve[255-sat];
  int r;
  int g;
  int b;
  int base;

  if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
    colors[0]=val;
    colors[1]=val;
    colors[2]=val;  
  } else  { 

    base = ((255 - sat) * val)>>8;

    switch(hue/60) {
	case 0:
		r = val;
		g = (((val-base)*hue)/60)+base;
		b = base;
	break;

	case 1:
		r = (((val-base)*(60-(hue%60)))/60)+base;
		g = val;
		b = base;
	break;

	case 2:
		r = base;
		g = val;
		b = (((val-base)*(hue%60))/60)+base;
	break;

	case 3:
		r = base;
		g = (((val-base)*(60-(hue%60)))/60)+base;
		b = val;
	break;

	case 4:
		r = (((val-base)*(hue%60))/60)+base;
		g = base;
		b = val;
	break;

	case 5:
		r = val;
		g = base;
		b = (((val-base)*(60-(hue%60)))/60)+base;
	break;
    }
    colors[0]=r;
    colors[1]=g;
    colors[2]=b;
    analogWrite(ledPinR, rgb_colors[0]);
    analogWrite(ledPinG, rgb_colors[1]);
    analogWrite(ledPinB, rgb_colors[2]);
  }
}  
//-----------------------------------------------------

Что может быть?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

maloicds пишет:

Что может быть?

А что там может быть, некорректная работа с памятью, конечно, других причин нет. А вот где эта некорректная работа - это искать надо.

Ну, первое место, где с памятью работаете некорректно видно сразу. Однако, не думаю, что именно это приводит к нестабильности. Но исправить всё равно надо. Давайте Вы исправите, запустите и отпишетесь как оно. Скорее всего придётся искать дальше, тогда будем искать.

Так, в строке 154 Вы вызываете функцию getRGB и третьим параметром передаёте brightness, которое у Вас бывает от 2 до 256. А в строке 203 Вы используете эту величину как индекс в массиве dim_curve. Но здесь нет ошибки (Вы удивлены?) потому что из-за мелкой описки (лишей запятой в конце строки 20) массив dim_curve у Вас имеет длину не 256 символов, как Вы очевидно хотели, а 257, поэтому пока всё нормально.

А вот в строке 160 уже ненормально - Вы вновь вызываете функцию  getRGB но  brightness при этом у Вас от  -1 до 253 и потому, в строке 203 Вы обращаетесь к минус-первому элементу массива - dim_curve[-1]. Это очевидная ошибка. Что там лежит мы не знаем и, значит, не знаем какое значение получит val.

Пока там только чтение - это врядли вызовет описанную Вами нестабильность, но val получило левое значение, дальше неприятности могут расти как снежный ком.

Давайте Вы это исправите и если не поможет (а боюсь, что не поможет), опубликуете свежий код и будем смотреть дальше.

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

ЕвгенийП, спасибо за обширный ответ!

Цветовые эффекты нашел в интернете и код особо не проверял :)

Проблема возникает при выполнении prog1 (mode=1), остальные режимы пока не стал трогать. При data.d9==0 (111 строка) всё отлично работает

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

При распашке памяти видимый эффкект может проявляться где угодно. Иногда совсем далеко от того места, где память распахали. То, что я Вам показал (отрицательный индекс при обращении к массиву) есть факт. Не хотите исправлять - дело Ваше. Удачи!

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Пересобрал код, непомогло :(

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
const byte dim_curve[] = {
  0,   1,   1,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,
  3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,   4,
  4,   4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,
  6,   6,   6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
  8,   8,   9,   9,   9,   9,   9,   9,   10,  10,  10,  10,  10,  11,  11,  11,
  11,  11,  12,  12,  12,  12,  12,  13,  13,  13,  13,  14,  14,  14,  14,  15,
  15,  15,  16,  16,  16,  16,  17,  17,  17,  18,  18,  18,  19,  19,  19,  20,
  20,  20,  21,  21,  22,  22,  22,  23,  23,  24,  24,  25,  25,  25,  26,  26,
  27,  27,  28,  28,  29,  29,  30,  30,  31,  32,  32,  33,  33,  34,  35,  35,
  36,  36,  37,  38,  38,  39,  40,  40,  41,  42,  43,  43,  44,  45,  46,  47,
  48,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
  63,  64,  65,  66,  68,  69,  70,  71,  73,  74,  75,  76,  78,  79,  81,  82,
  83,  85,  86,  88,  90,  91,  93,  94,  96,  98,  99,  101, 103, 105, 107, 109,
  110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
  146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
  193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};

typedef struct
{
  byte  d1; // number device
  int   d2; // vbat
  float d3; // temp
  float d4; // -
  byte  d5; // -
  byte  d6; // -
  byte  d7; // -
  byte  d8; // -
  byte  d9; // -
}
B_t;
B_t data;

RF24 radio(7, 8);  // make sure this corresponds to the pins you are using
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int ledPinR = 6;
int ledPinG = 10;
int ledPinB = 5;
int ledPinW = 9;
int mode = 0;
int r, g, b;

int rgb_colors[3];
int fadeSpeed = 2; // 'speed' of fading
//int saturation = 255;

int rgbColour[3];
long previousMillis = 0;
//---------- -----------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println("Start");
  radio.begin();
  radio.openReadingPipe(1, pipes[1]);
  radio.startListening();
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinG, OUTPUT);
  pinMode(ledPinB, OUTPUT);
  pinMode(ledPinW, OUTPUT);
  randomSeed(analogRead(0));
  prog3();
}
//---------- -----------------------------------------
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1000)
  {
    previousMillis = currentMillis;
    //    Serial.print("Mode=");
    Serial.println(freeRam());
  }
  read_rf();
  prog1();// strobe
  prog2();// ambient
  prog4(); // fade
//  prog3();// all clear
}
//---------------------------------------------------
//-------------------------------------------------------
void read_rf()
{
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read( &data, sizeof(data) );
      Serial.println("new data");
//      Serial.println(int (data.d5)); //r
//      Serial.println(int (data.d6)); //g
//      Serial.println(int (data.d7)); //b
//      Serial.println(int (data.d9)); //mode

      if (data.d1 == 16)
      {
        if (data.d9 == 0) //mode set rgb colorwhel
        {
          analogWrite(ledPinR, data.d5);
          analogWrite(ledPinG, data.d6);
          analogWrite(ledPinB, data.d7);
          mode = 0;
        }
        else if (data.d9 != 0)
        {
          mode = data.d9;
        }
      }
    }
  }
}
//--------------------------------------------------------------------------------------------------
void prog4()
{
if (mode==4)
 {
  for (int decColour = 0; decColour < 3; decColour += 1)
  {
    int incColour = decColour == 2 ? 0 : decColour + 1;
    for (int i = 0; i < 255; i += 1)
    {
      rgbColour[decColour] -= 1;
      rgbColour[incColour] += 1;
      analogWrite(ledPinR, rgbColour[0]);
      analogWrite(ledPinG, rgbColour[1]);
      analogWrite(ledPinB, rgbColour[2]);  
      delay(20);
    }
  }
 }
}
//---------- -----------------------------------------
void prog2()
{
  if (mode == 2)
  {
    int hue = random(360);
    for (int brightness = 0; brightness < 256; brightness++)
    {
 //     brightness = brightness + fadeSpeed;            // change fadeVal by speed
      getRGB(hue,  brightness ); // converts HSB to RGB
      delay(1); // delay to slow down fading

    }
    for (int brightness = 256; brightness > 0; brightness--)
    {
//      brightness = brightness - fadeSpeed;         // change fadeVal by speed
      getRGB(hue,  brightness); // converts HSB to RGB
//         Serial.println(brightness);
      delay(5); // delay to slow down fading
    }
    delay(1000);
  }
}
//---------- -----------------------------------------
void prog3()// all off
{
  analogWrite(ledPinR, 0);
  analogWrite(ledPinG, 0);
  analogWrite(ledPinB, 0);
  // mode=99;
}
//-------------------------------------------------------
void prog1()
{
  if (mode == 1)
  {
    r = random(256);
    g = random(256);
    b = random(256);
    cop_flash();
    delay (100);
    cop_flash();
    delay (100);
    cop_flash();
    delay (1000);
  }
}
//---------- -----------------------------------------
void cop_flash()
{
  analogWrite(ledPinR, r);
  analogWrite(ledPinG, g);
  analogWrite(ledPinB, b);
  delay(10);
  analogWrite(ledPinR, 0);
  analogWrite(ledPinG, 0);
  analogWrite(ledPinB, 0);
}
//----------------------------------------------------
void getRGB(int hue, int val)
{
  val = dim_curve[val];
  int sat = 255;// - dim_curve[255 - sat];
//  Serial.println(sat);
  
 int base = ((255 - sat) * val) >> 8; //????
    switch (hue / 60) {
      case 0:
        r = val;
        g = (((val - base) * hue) / 60) + base;
        b = base;
        break;

      case 1:
        r = (((val - base) * (60 - (hue % 60))) / 60) + base;
        g = val;
        b = base;
        break;

      case 2:
        r = base;
        g = val;
        b = (((val - base) * (hue % 60)) / 60) + base;
        break;

      case 3:
        r = base;
        g = (((val - base) * (60 - (hue % 60))) / 60) + base;
        b = val;
        break;

      case 4:
        r = (((val - base) * (hue % 60)) / 60) + base;
        g = base;
        b = val;
        break;

      case 5:
        r = val;
        g = base;
        b = (((val - base) * (60 - (hue % 60))) / 60) + base;
        break;
    }
    analogWrite(ledPinR, r);
    analogWrite(ledPinG, g);
    analogWrite(ledPinB, b);
 
}
//-----------------------------------------------------
int freeRam ()
{
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
//-----------------------------------------------------

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Заодно, уберите последнюю запятую в строке 20. Иначе там ещё один элемент массива бразуется.

Продолжаем смотреть.

В строке 51 объявлен массив rgbColour. В строках 127 и 128 элементы этого массива декремнтируются и инкрементируются соответственно. 

А где они получают значения? Инициализирутся ли они хоть как-нибудь? Я не нашёл. Покажите?

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Вопрос частично решен: отсоеденил катушку с лентой и все работает (в Serial стабильно идут данные)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, а значения-то неинициализированных переменных каковы? Смотрели?

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Да все подправил, проблема в железе 99%

araqel
Offline
Зарегистрирован: 12.08.2016

А можно получить весь проект для повторения?