Не могу понять - при чем тут delay ?!

Имеется вот такой простой почти что псевдо код:

#include <Arduino.h>

void LPD_RGBW_Solid();

#define  LEDS_NUM 16
volatile uint8_t ledColors[LEDS_NUM*3] = {0};

void setup() {
}

void loop() {
	LPD_RGBW_Solid();
	StripShow();
}


void LPD_RGBW_Solid(){
static uint8_t CC    = 0x01;
static int8_t  dir  = 1;
    
	CC += dir;
	if( CC == 0    ){ dir =  1;  }
	if( CC == 0xFF ){ dir = -1; }

	for( uint8_t ledNo=0, step=0; ledNo < LEDS_NUM; ledNo++, step++ ){
        uint8_t r,g,b;
		switch( step ){
			case 0:  r=CC; g= 0; b= 0; break;
			case 1:  r= 0; g=CC; b= 0; break;
			case 2:  r= 0; g= 0; b=CC; break;
			case 3:  r=CC; g=CC; b=CC; break;
			default: r= 0; g= 0; b= 0; step = 0; break;
		}
		ledColors[0+ledNo*3] = r;
		ledColors[1+ledNo*3] = g;
		ledColors[2+ledNo*3] = b;
	}
}

Функция LPD_RGBW_Solid наваливает в массив ledColors RGB составляющие для каждого светодиода:
n+0 - red
n+1 - green
n+2 - blue
n+3 - white
n+4 - black

Ну и при каждом обращении в loop увеличивает яркость каждого канала. Дошли до 0xFF - начали уменьшать. Дошли до 0 - начали увеличивать. Ну тупая ведь задача!!!

Функция StripShow(); - это уже реально выводит подготовленный массив на светодиоды.

Однако! Оно делает в реальности цикл вверх по яркости, вниз по яркости. Потом делает 3 раза мырг-мырг быстро ))))

Я уже просто в истерике. Не понимаю, где искать косяк!!!
И самое смешное, если в функции подготовки цветов ( в LPD_RGBW_Solid() ) сделать вот так:

	CC += dir;
	if( CC == 0    ){ dir =  1; delay(0); }
	if( CC == 0xFF ){ dir = -1; delay(0); }

И сразу всё начинает работать!
Блин! Откуда и зачем этот нулевой делэй так необходим???!!!

PS: Arduino Nano

Это не нулевой делей. А микросекундный.

Да хоть нано- и пико- секундный?! Почему с ним работает, а без него полная ерунда?!
Неужели заполнение массива происходит в каких-то прерываниях???!!!

Наверно оптимизатор мудрит. Надо дебажить, смотреть чего там происходит. Чего гадать-то?

Вы тут в соседней теме, написали

А я знаете чему удивляюсь? Как каждый раз одни и те же личности умудряются наступить ровно на те же самые грабли при формулировании вопроса? Вот, как? Альтернативно-одарённые! Не иначе!

Ну, вот сколько раз твердили миру (и лично Вам), что код нужно давать ПОЛНЫЙ (если Вы не знаете значения этого слова, посмотрите у Даля) и, кроме того, необходимо точно указывать какое именно оборудование используется.

Вот как мне отвечать на Ваш вопрос? Давайте попробую.

  1. Я предполагаю, что в Вашей функции StripShow нет проверки когда она вызывалась в последний раз. Оно, конечно, ХЗ, т.к. она секретная, но я предполагаю, что нет.
  2. Я предполагаю, что речь идёт об адресной ленте. Это ниоткуда не следует, но я предположу это.

Так, вот, если мои предположения верны, то скорее всего, Вы слишком часто её вызываете. Чтобы проверить эту гипотезу, уберите свои делеи и поставьте просто deay(1); перед вызовом функции StripShow (или после). Если заработает, то скорее всего это и есть.

А вот если мои предположения не верны, то я зря бил пальцы об клавиатуру. И чем чаще такое случается, тем меньше у меня желания помогать людям, вроде Вас, которым лень толком объяснить свою проблему.

Не знаю и знать не хочу!! Вот конкретно от вас не хочу ничего знать )))

Именно так! )))

Я вас очень попрошу в дальнейшем полностью игнорировать мои посты!!! Пожалуйста! Ваши комментарии мне не интересны никак!!! Спасибо!

Я, безусловно, буду иметь в виду Вашу просьбу, но я, знаете ли, всегда комментирую то, что хочу и так, как хочу, так что, не взыщите.

5 лайков

конечно секретная.
Это же та самая функция из ветки из срача про ленту, где автор утверждал, что все решил сам, без помощи, но продемонстрировать код отказался.

нет, только срач

Не… Ну когда по существу нет возможности ответить, то конечно надо бить на мелочи )))

Вот вам вся “секретная” функция - тупо дрыганье ногой МК согласно карте цветов ))))

/*-----------------------------------------------------------------------------
|                                      [ StripShow ]
+-----------------------------------------------------------------------------*/
void StripShow(){ 
	cli();
	for( uint8_t colorNo=0; colorNo < LEDS_NUM*3; colorNo++ ){

		asm volatile (
		"movw Z, %[colorOUT] \n"               // ptr = colorOUT
		"ldi r21, 2 \n"                        // byteNo = 2
		"ldi r22, 8 \n"                        // bitNo  = 8

		"loopByte: \n"                         // do {
			"ld r23, Z+ \n"                    //     color = ptr++[0]
			
			"loopBit: \n"                      //     do {
				"lsr r23 \n"                   //         check color.bit0 and color >> 1
				"brcs Code1 \n"                //         if( bit0 == 1 ) goto Code1 else
				"Code0: \n"                    //         Code0
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T0H
					"nop \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T0L
					"rjmp EndOfCode \n"        //
				"Code1: \n"                    //         Code1
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T1H
					"ldi R16, 3 \n loopT1H:  dec r16 \n brne loopT1H \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T1L
				"EndOfCode: \n"                //
				"dec r22 \n brne loopBit \n"   //     } while( --bitNo > 0 )

			"ldi r22, 4 \n"                    //     bitNo = 4
			"dec r21 \n brne loopByte \n"      // } while( --byteNo > 0 )
		:
		: [colorOUT] "r" ((uint8_t *)&ColorMap[ledColors[colorNo]])
		);
	}

	sei();
}

Стало значительно легче? ))))))

Понятно.

Конечно! Теперь я вижу, что никакой проверки времени предыдущего вызова нет. Значит, причина такого поведения понятна и я её уже озвучил. Правда, вместо благодарности, огрёб, бывает. И Вам не хворать.

Ну да. Чел, вроде как чего то просит, не может понять… И тут же х. обкладывает помогающих. Оригинально-с.

3 лайка

Да я потому и написал - “почти что псевдо код”
Там просто еще много чего “под капотом”, что к вопросу не имеет отношения.
Ну если интересно, то вот полный код… Извиняюсь, но не буду вычищать все свои попутные экспериментальные комменты…

Спойлер main.cpp
#include <Arduino.h>
#include <util/atomic.h>
#include <avr/pgmspace.h>


#include "GyverIO.h"

#include "HamperUtils.h"
#include "LPD1886_LED.h"
#include "LPD1886_Effects.h"

/*-----------------------------------------------------------------------------
|                                      [ setup ]
+-----------------------------------------------------------------------------*/
void setup() {
	Serial.begin(115200); //,SERIAL_8N1,SERIAL_TX_ONLY);
	while(!Serial) delay(0);

	Serial.printf("\n===========================================");
	Serial.printf("\n| CPU %ld MHz |", F_CPU / 1000000);
	Serial.printf("\n===========================================\n");

	pinMode( 9, OUTPUT);
	pinMode(10, OUTPUT);

	TCCR1A = 0;
	TCCR1B = 0;

	LPD_Init();
} 
// ------------------------------------- [/ setup ]



/*-----------------------------------------------------------------------------
|                                      [ loop ]
+-----------------------------------------------------------------------------*/
void loop() {

	//LPD_One_Color(0x10,0x80,0);
	//LPD_RGBW_Solid(); delay(5);
	//LPD_360Angle(0.55);
	LPD_Rainbow_Fade(); delay(55);
	//LPD_Rainbow_Loop(); delay(50);
	//LPD_Matrix(); delay(110);
	//LPD_Stars(); delay(110);

	float timerValue;
	TCCR1B = 0; TCNT1 = 0; TCCR1B = 1;
	// ---------- исследуемый программный блок ---------

	StripShow();


	// -------------------------------------------------
	TCCR1B = 0; timerValue = (TCNT1-2) * 62.5;
	// вывод результата
	//Serial.print( timerValue, 0 ); Serial.print(" ns  ("); Serial.print( timerValue/1000, 2 ); Serial.print("us)  "); Serial.print( TCNT1 ); Serial.println(" tick");
	//delay(250);

	
}
// ------------------------------------- [/ loop ]
Спойлер LPD1886_LED.h
#pragma once

#include <Arduino.h>
#include <util/atomic.h>

#define D9_Low  PORTB &= B11111001
#define D9_High PORTB |= B00000110

#define  LEDS_NUM 16
volatile uint8_t ledColors[LEDS_NUM*3] = {0};


static const uint8_t  TableBitReverse[] = {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
static const uint16_t BitMask [] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000};
static const uint8_t  BitMask8[] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
volatile     uint16_t ColorMap[0x100];

#define color12(x) ({                              \
	uint16_t c12 = (x<<4) | (x>>4);                \
	uint16_t r;                                    \
	r  = TableBitReverse[ (c12     ) & 0xF ];      \
	r |= TableBitReverse[ (c12 >> 4) & 0xF ] << 8; \
	r |= TableBitReverse[ (c12 >> 8) & 0xF ] << 4; \
})


typedef struct {
    uint8_t h;
    uint8_t s;
    uint8_t v;
} hsv;

typedef struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
} rgb;


/*-----------------------------------------------------------------------------
|                                      [ LPD_Init ]
+-----------------------------------------------------------------------------*/
void LPD_Init(){
	for( uint16_t i=0; i <= 0xFF; i++ ){
		ColorMap[i] = i;
		if( i < 44 ){
			ColorMap[i] = color12( (uint16_t)((i+1)*0.17) );
		} else {
			//ColorMap[i] = 0xfff & (((uint32_t)(i + 2) * (uint32_t)(i + 1) * (uint32_t)i) >> 16); // кубическая гамма 8 bit
			ColorMap[i] = ((uint16_t)(i+1) * (i) + 255) >> 8; // квадратная гамма 8bit
			ColorMap[i] = color12(ColorMap[i]);
		}
	}
}
// ------------------------------------- [/ LPD_Init ]





/*-----------------------------------------------------------------------------
|                                      [ StripShow ]
+-----------------------------------------------------------------------------*/
void StripShow(){ 
	cli();
	for( uint8_t colorNo=0; colorNo < LEDS_NUM*3; colorNo++ ){

		asm volatile (
		"movw Z, %[colorOUT] \n"               // ptr = colorOUT
		"ldi r21, 2 \n"                        // byteNo = 2
		"ldi r22, 8 \n"                        // bitNo  = 8

		"loopByte: \n"                         // do {
			"ld r23, Z+ \n"                    //     color = ptr++[0]
			
			"loopBit: \n"                      //     do {
				"lsr r23 \n"                   //         check color.bit0 and color >> 1
				"brcs Code1 \n"                //         if( bit0 == 1 ) goto Code1 else
				"Code0: \n"                    //         Code0
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T0H
					"nop \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T0L
					"rjmp EndOfCode \n"        //
				"Code1: \n"                    //         Code1
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T1H
					"ldi R16, 3 \n loopT1H:  dec r16 \n brne loopT1H \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T1L
				"EndOfCode: \n"                //
				"dec r22 \n brne loopBit \n"   //     } while( --bitNo > 0 )

			"ldi r22, 4 \n"                    //     bitNo = 4
			"dec r21 \n brne loopByte \n"      // } while( --byteNo > 0 )
		:
		: [colorOUT] "r" ((uint8_t *)&ColorMap[ledColors[colorNo]])
		);
	}

	sei();
	return;
/*


uint8_t   bitNo;
uint8_t   bitVal;
uint16_t  color;

	while( colorNo < LEDS_NUM*3 ){
		//if(DEBUG){ Serial.printf( "%03x %03x %03x | ", ColorMap[ledColors[0+colorNo]], ColorMap[ledColors[1+colorNo]], ColorMap[ledColors[2+colorNo]] ); }


		color = ColorMap[ledColors[colorNo]];
		bitNo = 0;
		while( bitNo < 12 ){
			bitVal = (color & BitMask[bitNo]) > 0;

			if( bitVal ){ 
				asm volatile (
					"Code_1:\n"
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T1H
					"ldi R16, 3 \n loopT1H:  dec r16 \n brne loopT1H \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T1L
				);
			} else { 
				asm volatile (
					"Code_0:\n"
					"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T0H
					"nop \n"
					"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T0L
				);
			}
			bitNo++;
		}

		colorNo++;
	}

	return;





	//Serial.println(ledColors[0]);
	asm volatile (
		"ldi r26, 0xc1  \n" //load register r26 with 42
		"ld r26, %a[ledColors]+  \n" //load register r26 with 42
		"ld r26, %a[ledColors]  \n" //load register r26 with 42
		"sts (a), r26 \n" //store r26 into memory location of variable a
		:
		: [ledColors] "e" (ledColors), [ColorMap] "e" (ColorMap)
		);
		Serial.printf("%02x %02x %02x  -  %04x\n", ledColors[0], ledColors[1], ledColors[2], a);
		return;
	
	
		//X - r27:r26
		//Y - r29:r28
		//Z - r31:r30
	
		// r20 - loopLED
		// r21 - loopColor
		// r22 - BitLoop
		asm volatile (
			"cli \n"
	
			"ldi r20, 100 \n" // 100 LED
			"loopLed: \n"		
	
				"ldi r21, 3 \n" // 3channel
				"loopColor: \n"
	
					"ldi r22, 12 \n" // 12bit per channel
					"BitLoop:\n"
	
						"rjmp Code_0 \n"
	
						"retFromCode: \n"
	
						"dec r22 \n   brne BitLoop \n"
					"dec r21 \n   brne loopColor \n"
				"dec r20 \n   brne loopLed \n"
	
			"rjmp EndOf \n"
	
	
		"Code_0:\n"
			"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T0H
			"nop \n"
			"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T0L
			"rjmp retFromCode \n"
	
		"Code_1:\n"
			"ldi R16, 0b00000110 \n		out 0x05, R16 \n" // T1H
			"ldi R16, 3 \n loopT1H:  dec r16 \n brne loopT1H \n"
			"ldi R16, 0b11111001 \n		out 0x05, R16 \n" // T1L
			"rjmp retFromCode \n"
	
		"EndOf: \n"
			"sei \n"
	
		:: );
		return;
	
*/		
}
// ------------------------------------- [/ StripShow ]

Спойлер LPD1886_Effects.h
#pragma once
#include "LPD1886_LED.h"


//val = (exp(sin(millis()/2000.0 * PI)) - 0.368) * 108.0; //breath
void HSV( uint8_t *led,  uint8_t h, uint8_t s, uint8_t v ); // обычный HSV
static hsv rgb2hsv( const uint8_t *led );



void LPD_Rainbow_Fade() {                         //-m2-FADE ALL LEDS THROUGH HSV RAINBOW
static uint8_t ihue = 0;
    ihue++;
    for( uint8_t idex = 0 ; idex < LEDS_NUM; idex++ ) {
        HSV( (uint8_t *)&ledColors[idex*3], ihue, 255, 64 );
    }
}


void LPD_Rainbow_Loop() {                        //-m3-LOOP HSV RAINBOW
static uint16_t idex = 0;
static uint8_t  thisstep = 3;
static uint8_t  ihue = 0;
    
    idex++;
    ihue += thisstep;
    if( idex >= LEDS_NUM ) idex = 0;

    HSV( (uint8_t *)&ledColors[idex*3], ihue, 255, 32 );
 }



void LPD_Matrix() {                                   //-m29-ONE LINE MATRIX
static uint8_t  thishue = 0;
uint16_t const  lastNo = LEDS_NUM - 1;
rgb            *l0, *l1;

    for( uint16_t i=0; i < lastNo; i++ ) {
        l0 = (rgb *)&ledColors[(i  )*3];
        l1 = (rgb *)&ledColors[(i+1)*3];
        l0->r = l1->r;
        l0->g = l1->g;
        l0->b = l1->b;
    }

    if( random(0, 100) > 89 ) {
        thishue += 4;
        HSV( (uint8_t *)&ledColors[lastNo*3], thishue, 255, 0xFF );
    }
    else {
        HSV( (uint8_t *)&ledColors[lastNo*3], thishue, 255,   0 );
    }

    hsv hsv0, hsv1;
    hsv0 = rgb2hsv( (uint8_t *)&ledColors[lastNo*3] );
    if( hsv0.v == 0 ){
        hsv1 = rgb2hsv( (uint8_t *)&ledColors[(lastNo-1)*3] );
        if( hsv1.v == 0xFF ){
            HSV( (uint8_t *)&ledColors[lastNo*3], hsv1.h, hsv1.s, 0x80 );
        } else if( hsv1.v == 0x80 ){
            HSV( (uint8_t *)&ledColors[lastNo*3], hsv1.h, hsv1.s, 0x20 );
        }
    } 

 }
  

void LPD_Stars(){
static uint8_t  thishue = 0;

    thishue += 19;

    for( uint16_t i=0; i < LEDS_NUM; i++ ) {
        hsv hsv0 = rgb2hsv( (uint8_t *)&ledColors[i*3] );
        //hsv0.v >>= (random(0,100) > 30) ? 1 : 0;
        if( hsv0.v > 0 ){
            hsv0.v -= 51;
            HSV( (uint8_t *)&ledColors[i*3], hsv0.h, hsv0.s, hsv0.v  );
        }
    }

    if( random(0, 100) > 80 ){
        uint16_t newStar = (uint16_t)random( 0, LEDS_NUM - 1 );
        HSV( (uint8_t *)&ledColors[newStar*3], thishue, 255, 255 );
    }
}



void LPD_360Angle( float Step = 0.55 ){
static float  AngleR = 0.0, AngleG = 45.0, AngleB = 135.0;
float  val, mult = 5.0;

    AngleR += Step;
    AngleG += Step;
    AngleB += Step;

    for( uint16_t ledNo=0; ledNo < LEDS_NUM; ledNo++ ){
        val = (sin((AngleR+(Step*mult)*ledNo) * 0.0174533) + 1) * 128; 
        ledColors[0+ledNo*3] = (uint8_t) val;

        val = (sin((AngleG+(Step*mult)*ledNo) * 0.0174533) + 1) * 128; 
        ledColors[1+ledNo*3] = (uint8_t) val;

        val = (sin((AngleB+(Step*mult)*ledNo) * 0.0174533) + 1) * 128; 
        ledColors[2+ledNo*3] = (uint8_t) val;
    }

}


void LPD_RGBW_Solid(){
static uint8_t CC    = 0x01;
static int8_t  dir  = 1;
    
	CC += dir;
	if( CC == 0    ){ dir =  1; delay(0); }
	if( CC == 0xFF ){ dir = -1; delay(0); }

	for( uint8_t ledNo=0, step=0; ledNo < LEDS_NUM; ledNo++, step++ ){
        uint8_t r,g,b;
		switch( step ){
			case 0:  r=CC; g= 0; b= 0; break;
			case 1:  r= 0; g=CC; b= 0; break;
			case 2:  r= 0; g= 0; b=CC; break;
			case 3:  r=CC; g=CC; b=CC; break;
			default: r= 0; g= 0; b= 0; step = 0; break;
		}
		ledColors[0+ledNo*3] = r;
		ledColors[1+ledNo*3] = g;
		ledColors[2+ledNo*3] = b;
	}
}



void LPD_One_Color( const uint8_t r=0x80, const uint8_t g=0, const uint8_t b=0 ){
	for( uint16_t ledNo=0; ledNo < LEDS_NUM; ledNo++ ){
		ledColors[0+ledNo*3] = r;
		ledColors[1+ledNo*3] = g;
		ledColors[2+ledNo*3] = b;
    }
}









// обычный HSV
void HSV( uint8_t *led,  uint8_t h, uint8_t s, uint8_t v ) {
    float r=0, g=0, b=0;
    
    float H = h / 255.0;
    float S = s / 255.0;
    float V = v / 255.0;
    
    int   i = int(H * 6);
    float f = H * 6 - i;
    float p = V * (1 - S);
    float q = V * (1 - f * S);
    float t = V * (1 - (1 - f) * S);
    
    switch (i % 6) {
    case 0: r = V, g = t, b = p; break;
    case 1: r = q, g = V, b = p; break;
    case 2: r = p, g = V, b = t; break;
    case 3: r = p, g = q, b = V; break;
    case 4: r = t, g = p, b = V; break;
    case 5: r = V, g = p, b = q; break;	
    }
    led[0] = r * 255.0;
    led[1] = g * 255.0;
    led[2] = b * 255.0;
}




static hsv rgb2hsv( const uint8_t *led  ){
    hsv     out;
    uint8_t rgbMin, rgbMax;
    uint8_t r = led[0], g =led[1], b =led[2];

    rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
    rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
    
    out.v = rgbMax;
    if( out.v == 0 ){
        out.h = 0;
        out.s = 0;
        return out;
    }

    uint8_t max_min_diff = (rgbMax - rgbMin);

    out.s = 255 * long(max_min_diff) / out.v;
    if( out.s == 0 ){
        out.h = 0;
        return out;
    }

         if( rgbMax == r ) out.h =   0 + 43 * (g - b) / max_min_diff;
    else if( rgbMax == g ) out.h =  85 + 43 * (b - r) / max_min_diff;
    else                   out.h = 171 + 43 * (r - g) / max_min_diff;

    return out;
}
Спойлер platformio.ini
[env:nanoatmega328]
platform = atmelavr
framework = arduino
board = nanoatmega328
board_build.mcu = atmega328p
board_build.f_cpu = 16000000L
monitor_speed = 115200
upload_speed = 115200
lib_deps = 
	gyverlibs/GyverIO @ ^1.3.9

А ведь вопрос в задачнике звучит просто:
Почему вот так НЕ работает

CC += dir;
	if( CC == 0    ){ dir =  1;  }
	if( CC == 0xFF ){ dir = -1; }

А вот так работает как ожидается :

CC += dir;
	if( CC == 0    ){ dir =  1; delay(0); }
	if( CC == 0xFF ){ dir = -1; delay(0); }

Аргумент в delay не имеет значения! Можно ставить 0, можно 1 или еще что-то.

Весь остальной код остаётся не изменным!

Arduino Nano. ATmega328Р

Попробуйте делей поперемещать. Например, вынести его из функции наружу

Не понимаю. Нормальные люди, специалисты, от нех. делать отвечают какому то явному говну, Вот что противно.
Понятно, я могу ошибаться, но судя по манерам…, по разговору…
Или же это от нефиг делать, от бесцельной траты времени?

Оно самое.

PS:
Хорош сраться! Хорош пиписьками меряться! Каждую ветку, натурально, переводят в срач. И “…всяк другого мнит уродом, не смотря, что сам урод”

1 лайк

Да, да! Сам по своему урод.(