Nano vs Mega

Работал долго на Nano с RGB-лентой. Перешел на Mega.
Один и тот же код (несколько скетчей по кругу) более менее стабильно работает на Nano, но виснет в одном и том же месте на Mega.
Может есть какие-то нюансы с инициализацией? Прерывание какое может надо запретить?
Или банально глючная mega? Но тоже странно. Шьется, стартует.

VS=versus?

Да. Пытаюсь перейти с nano на mega. Если быть более точным - Mega 2560 PRO MINI.

научились исполнять несколько скетчей на одном МК? - покажите…

.

…Водители Ларионов и Кутько, используя один двигатель на две бортовые машины…

1 лайк

Все это возможно и даже более того, ответить внятно можно только имея перед глазами код

Mega живая. заливал на нее старый проект - все четко.

код криво вставляется. выложил по ссылке архивчик (https://cloud.mail.ru/public/58sG/jgch4foHq).
стабильно зависает на 4м case в custommodes() на Mega. Причем похоже неважно какой скетч там будет.
На nano работает постабильней, но глюки в 1м case проскакивают. А иногда (через 2-3 часа) вообще подвисает.

Дело похоже или в кривости штатных функций, или же есть какие-то прерывания, которые иногда некорректно отрабатывают (сталкивался на с таким на z80).

upd. в меге виснет на case 2:

@ae485 выложи код нормально. Честно пытался по ссылке глянуть, но там приложение требует.

1 лайк

Не видно никакого case 2 в теме,

если кто-то думает что кто-то здесь на форуме более заинтересован в проблеме тс, чем сам тс, то боюсь он ошибается :slight_smile:

1 лайк

Будем откровенны, весь форум на ушах теперь без сна🤣

2 лайка

Есессно. Не зря же гайвер своё ядро писал. Ардуина кривая, как ятаган. А ещё и китайские контроллеры, которые через поделку Билли зашиваются.
Буквально под каждым кустом насрано.
Поэтому только генту, vi, assembler и Байкал. Непременно под колокольный перезвон на Марью-искусницу.

2 лайка
#include <FastLED.h>

#define WIDTH 16
#define HEIGHT 16
#define NUM_LEDS WIDTH * HEIGHT
#define DATA_PIN 6


CRGB leds[NUM_LEDS];

int AUTOPLAY_PERIOD = 10;  

uint32_t autoplayTime = ((long)AUTOPLAY_PERIOD * 1000);
uint32_t autoplayTimer;

byte thisMode = 0;
bool loadingFlag = true;

void setup() { 
     FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  // GRB ordering is typical
     FastLED.setBrightness (255);
     Serial.begin(9600);
     Serial.println("done.");
     autoplayTimer = millis();
}

void loop() {
    customModes();
    ModeInc ();
    FastLED.show();  
}

#define MODES_AMOUNT 6

void customModes () {

  switch (thisMode) {
    case 0: SinShort();
      break;
    case 1: Ex9NiceOne();
      break;
    case 2: PlasmBall();
      delay(16);
      break;
    case 3: ColoredBursts();
      delay(30);
      break;
    case 4: RainbowTunnel();
      break;
    case 5: DNASpiraleHoriz();
      break;
  }
}

void ModeInc() {

 if (millis() - autoplayTimer > autoplayTime) {
    FastLED.clear();
    loadingFlag = true;
    thisMode++;
    if (thisMode >= MODES_AMOUNT) thisMode = 0;
    Serial.println(thisMode);
    autoplayTimer = millis();
  }
}

uint16_t XY( uint8_t x, uint8_t y) {
  uint16_t i;

    if( y & 0x01) {
      uint8_t reverseX = (WIDTH - 1) - x;
      i = (y * WIDTH) + reverseX;
    } else {
      i = (y * WIDTH) + x;
    }
    return i;
}

void drawPixelXYF_X(float x, uint16_t y,
  const CRGB & color) {
  uint8_t xx = (x - (int) x) * 255, ix = 255 - xx;
  uint8_t wu[2] = { ix, xx };
  for (int8_t i = 1; i >= 0; i--) {
    int16_t xn = x + (i & 1);
    CRGB clr = leds[XY(xn, y)];
      clr.r = qadd8(clr.r, (color.r * wu[i]) >> 8);
      clr.g = qadd8(clr.g, (color.g * wu[i]) >> 8);
      clr.b = qadd8(clr.b, (color.b * wu[i]) >> 8);
    leds[XY(xn, y)] = clr;
  }
}

void mydrawLine(byte x, byte y, byte x1, byte y1, CRGB color, bool dot, bool grad) {
  
  byte xsteps = abs8(x - x1) + 1;
  byte ysteps = abs8(y - y1) + 1;
  byte steps = xsteps >= ysteps ? xsteps : ysteps;
  
  for (byte i = 1; i <= steps; i++) {
    byte dx = lerp8by8(x, x1, i * 255 / steps);
    byte dy = lerp8by8(y, y1, i * 255 / steps);
    
    int index = XY(dx, dy);
    leds[index] += color; 
    if (grad) leds[index] %= (i * 255 / steps); 
   }
  
  if (dot) {
    leds[XY(x, y)] += CRGB::White;
    leds[XY(x1, y1)] += CRGB::White;
  }
}

void mydrawLine_DNA(byte y, byte y1, byte x, CRGB color, bool dot, bool grad) {
  
  byte steps = abs8(y - y1) + 1;
    for (byte i = 1; i <= steps; i++) {
    byte dy = lerp8by8(y, y1, i * 255 / steps);
    int index = XY(x, dy);
    leds[index] += color; 
    if (grad) leds[index] %= (i * 255 / steps); 
  }
    if (dot) { 
    leds[XY(x, y)] += CRGB::DarkSlateGray;
    leds[XY(x, y1)] += CRGB::White;
  }
}

#define a (256 / WIDTH)

void SinShort() {

  double t = (float)millis()/10;
    for (byte i = 0; i < HEIGHT; i++) {
    uint16_t shift = (i * 16); float sin1 = (1+sin(radians(t + shift)))*128; byte bright =  112*(1+sin(radians(t + shift + 90)))+30; byte bright2 =  112*(1+sin(radians(t + shift + 270)))+30;
    drawPixelXYF_X(sin1 /a, i, CHSV(sin1, 255, bright));
    drawPixelXYF_X((WIDTH-1)-(sin1 / a), i, CHSV(~(byte)sin1, 255, bright2));
  }
  fadeToBlackBy(leds, NUM_LEDS, 64);
  }

const uint8_t kBorderWidth = 2;

void Ex9NiceOne() {
  uint8_t blurAmount = 20;
  blur2d(leds, WIDTH, HEIGHT, blurAmount);

  uint8_t i = beatsin8(27, kBorderWidth, HEIGHT - kBorderWidth);
  uint8_t j = beatsin8(41, kBorderWidth, WIDTH - kBorderWidth);
    uint8_t ni = (WIDTH - 1) - i;
  uint8_t nj = (WIDTH - 1) - j;

   uint16_t ms = millis();
  leds[XY(i, j)] += CHSV(ms / 11, 200, 255);
  leds[XY(j, i)] += CHSV(ms / 13, 200, 255);
  leds[XY(ni, nj)] += CHSV(ms / 17, 200, 255);
  leds[XY(nj, ni)] += CHSV(ms / 29, 200, 255);
  leds[XY(i, nj)] += CHSV(ms / 37, 200, 255);
  leds[XY(ni, j)] += CHSV(ms / 41, 200, 255);
}

void PlasmBall() {

fadeToBlackBy(leds, NUM_LEDS, 16);
  double t = millis()/16;
  for (byte i = 0; i < WIDTH; i++) {
    byte thisVal = inoise8(i * 30, t, t);
    byte thisMax = map(thisVal, 0, 255, 0, WIDTH);
    for (byte j = 0; j < HEIGHT; j++) {
      byte thisVal_ = inoise8(t, j * 30, t);
      byte thisMax_ = map(thisVal_, 0, 255, 0, HEIGHT);
      byte x = (i+thisMax_ -(WIDTH * 2 - WIDTH) / 2);
      byte y = (j+thisMax -(WIDTH * 2 - WIDTH) / 2);
      byte cx = (i+thisMax_);
      byte cy = (j+thisMax);
      leds[XY(i, j)] += ((x-y > -2) && (x-y < 2)) || ((WIDTH - 1 - x-y) > -2 && (WIDTH - 1 - x-y < 2)) || (WIDTH - cx == 0) || (WIDTH - 1 - cx == 0) || ((HEIGHT - cy == 0) || (HEIGHT - 1 - cy == 0)) ? CHSV(beat8(5), thisVal_, thisVal) : CHSV(0, 0, 0);
    }
  }
    blur2d(leds, WIDTH, HEIGHT, 16);
}

void ColoredBursts () {
 static byte hue = 0;
  static byte numLines = 10;
  
  EVERY_N_MILLISECONDS(30) { hue++; } 
  EVERY_N_MILLISECONDS(1000) {
    if (random8(2)) {
      numLines++;
      if (numLines > 15) numLines = 15;
    } else { numLines--; if (numLines < 5) numLines = 5; }
  }
  
  #define speed - 5
  fadeToBlackBy(leds, NUM_LEDS, 40);
  
  for (byte i = 0; i < numLines; i++) {
    
    byte x1 = beatsin8(12 + speed, 0, (WIDTH - 1));
    byte x2 = beatsin8(10 + speed, 0, (WIDTH - 1));
    byte y1 = beatsin8(25 + speed, 0, (HEIGHT - 1), 0, i * 24);
    byte y2 = beatsin8(20 + speed, 0, (HEIGHT - 1), 0, i * 48 + 64);
    
    CRGB color = CHSV(i * 255 / numLines + hue, 255, 255);
    mydrawLine(x1, x2, y1, y2, color, 0, 1); 
 }
    blur2d(leds, WIDTH, HEIGHT, 8);
}

const uint8_t C_X = WIDTH / 2; 
const uint8_t C_Y = HEIGHT / 2; 
const uint8_t mapp = 255 / WIDTH;

struct {
  uint8_t angle;
  uint8_t radius;
}
rMap[WIDTH][HEIGHT]; 

void RainbowTunnel () {

FastLED.clear();
 if (loadingFlag) {
    loadingFlag = false;
    for (int8_t x = -C_X; x < C_X + (WIDTH % 2); x++) {
      for (int8_t y = -C_Y; y < C_Y + (HEIGHT % 2); y++) {
        rMap[x + C_X][y + C_Y].angle = 128 * (atan2(y, x) / PI);
        rMap[x + C_X][y + C_Y].radius = hypot(x, y) * mapp; 
      }
    }
  }
  static byte scaleX = 4;
  static byte scaleY = 4;

  static byte rt_speed = 2;
  static uint16_t t;
  t += rt_speed;
  for (uint8_t x = 0; x < WIDTH; x++) {
    for (uint8_t y = 0; y < HEIGHT; y++) {
      byte angle = rMap[x][y].angle;
      byte radius = rMap[x][y].radius;
      leds[XY(x, y)] = CHSV((angle*scaleX)-t+(radius*scaleY), 255, constrain(radius*2,0,255));
    }
  }
}

#define DNA_speeds 40
#define DNA_freq 6

void DNASpiraleHoriz() {

static byte hue = 0;
  int ms = millis() / 10;
  nscale8(leds, NUM_LEDS, 120);
  
	for (int i = 0; i < WIDTH; i++) {
		int y = beatsin8(DNA_speeds, 0, WIDTH - 1, 0, i * DNA_freq) + beatsin8(DNA_speeds - 7, 0, WIDTH - 1, 0, i * DNA_freq + 128);
		int y1 = beatsin8(DNA_speeds, 0, WIDTH - 1, 0, 128 + i * DNA_freq) + beatsin8(DNA_speeds - 7, 0, WIDTH - 1, 0, 128 + 64 + i * DNA_freq); 
    
		hue = i * 128 / (WIDTH - 1) + ms;
		CRGB color = CHSV(hue, 255, 255);
    
		if ((i + ms / 8) & 3) mydrawLine_DNA(y / 2, y1 / 2, i, color, 1, 1);
	}
}

Очевидно, что возможна как программная так и “железная” причина - например сбои по питанию.

  • При полностью отключенной ленте все рано зависает?
  • Зависает при первой же попытке вывести определенный режим или на какой попытке?
  • Как программный вариант можно переписать функцию
    uint16_t XY( uint8_t x, uint8_t y)
    добавив контроль не выхода возвращаемого значения за (NUM_LEDS - 1) и сообщать в serial, если такое превышение случилось.

Добавление: в void RainbowTunnel () тоже используется запись в массив по результатам вычислений - добавьте и там контроль не выхода за границы массива.

  1. Попробовал с отключенной лентой - перестало зависать.
    Померял ток - в пике до 1.13А (из них мега - 40mA). Поставил БП помощней, на 2.1А, подключил ленту, все равно зависло в том же месте на case 2 (0.6А показывало).
  2. Зависает конкретный sub - PlasmBall. (upd. это не точно, требует уточнений).
  3. Контроль выхода для XY поправил:
uint16_t XY( uint8_t x, uint8_t y)
{
  uint16_t i;

    if( y & 0x01) {
      uint8_t reverseX = (WIDTH - 1) - x;
      i = (y * WIDTH) + reverseX;
    } else {
      i = (y * WIDTH) + x;
    }
    if (i > (NUM_LEDS-1)) 
    {
      i=NUM_LEDS - 1;
      Serial.println("XY out of bonds");
    }
    return i;
} 

продолжаю эксперименты.

Странно. У меня в симуляторе для режима 0 выводятся сообщения о выходе за границу индекса (с вашим измененным кодом).

У вас нет этих сообщений?

Вина БП проверяется просто - общая яркость выставляется на 32 или 16.

Хуже нет таких вопросов: “на Нано работает криво, а вот на Меге ЕЩЁ кривее. Пачиму?”

Итого, что помогло 100% - снижение яркости, пока до

Так ведь хочется чтобы в жизни было чудо, но нет, везде холодные цифры. А остальное - эмоции. Особенно трудно ветеринарам и разрабам, не имеющим возможности код отдебажить.

По сути:

  1. снижение ярости до 30 помогло. Похоже это основное из-за чего проблемы были. Очень нелинейный ход. Я в таких случаях до сих пор обычно шел по пути увеличения ТТХ БП по току.
  2. Выход за рамки немного иначе стал отслеживать - на уровне входящих x и y. Действительно все вылеты в case0 (-1, +1 отловил). Хотя глобально думаю это не особо критично, т.к. это просто адресация к несуществующему светодиоду, что по идее не ведет к зависанию. Поправьте если не прав. upd. Но это критично, если есть выделенный массив размера W*H, там однозначно будет ошибка out of bounds.

Значит БП не тащит на некоторых эффектах, где светодиоды начинают потреблять излишнее - много белого, много активных пикселей.