Работал долго на Nano с RGB-лентой. Перешел на Mega.
Один и тот же код (несколько скетчей по кругу) более менее стабильно работает на Nano, но виснет в одном и том же месте на Mega.
Может есть какие-то нюансы с инициализацией? Прерывание какое может надо запретить?
Или банально глючная mega? Но тоже странно. Шьется, стартует.
VS=versus?
Да. Пытаюсь перейти с nano на mega. Если быть более точным - Mega 2560 PRO MINI.
научились исполнять несколько скетчей на одном МК? - покажите…
.
…Водители Ларионов и Кутько, используя один двигатель на две бортовые машины…
Все это возможно и даже более того, ответить внятно можно только имея перед глазами код
Mega живая. заливал на нее старый проект - все четко.
код криво вставляется. выложил по ссылке архивчик (https://cloud.mail.ru/public/58sG/jgch4foHq).
стабильно зависает на 4м case в custommodes() на Mega. Причем похоже неважно какой скетч там будет.
На nano работает постабильней, но глюки в 1м case проскакивают. А иногда (через 2-3 часа) вообще подвисает.
Дело похоже или в кривости штатных функций, или же есть какие-то прерывания, которые иногда некорректно отрабатывают (сталкивался на с таким на z80).
upd. в меге виснет на case 2:
@ae485 выложи код нормально. Честно пытался по ссылке глянуть, но там приложение требует.
Не видно никакого case 2 в теме,
если кто-то думает что кто-то здесь на форуме более заинтересован в проблеме тс, чем сам тс, то боюсь он ошибается
Будем откровенны, весь форум на ушах теперь без сна🤣
Есессно. Не зря же гайвер своё ядро писал. Ардуина кривая, как ятаган. А ещё и китайские контроллеры, которые через поделку Билли зашиваются.
Буквально под каждым кустом насрано.
Поэтому только генту, vi, assembler и Байкал. Непременно под колокольный перезвон на Марью-искусницу.
#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.13А (из них мега - 40mA). Поставил БП помощней, на 2.1А, подключил ленту, все равно зависло в том же месте на case 2 (0.6А показывало). - Зависает конкретный sub - PlasmBall. (upd. это не точно, требует уточнений).
- Контроль выхода для 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% - снижение яркости, пока до
Так ведь хочется чтобы в жизни было чудо, но нет, везде холодные цифры. А остальное - эмоции. Особенно трудно ветеринарам и разрабам, не имеющим возможности код отдебажить.
По сути:
- снижение ярости до 30 помогло. Похоже это основное из-за чего проблемы были. Очень нелинейный ход. Я в таких случаях до сих пор обычно шел по пути увеличения ТТХ БП по току.
- Выход за рамки немного иначе стал отслеживать - на уровне входящих x и y. Действительно все вылеты в case0 (-1, +1 отловил). Хотя глобально думаю это не особо критично, т.к. это просто адресация к несуществующему светодиоду, что по идее не ведет к зависанию. Поправьте если не прав. upd. Но это критично, если есть выделенный массив размера W*H, там однозначно будет ошибка out of bounds.
Значит БП не тащит на некоторых эффектах, где светодиоды начинают потреблять излишнее - много белого, много активных пикселей.