STM8S-Discovery and WS2812B RGB Led

 Numa compra de impulso acabei por ter na minha caixa de correio nem mais nem menos que 100 Leds RGB

Banggood WS2812B

WS2812B

Datasheet WS2812B

A ideia pareceu boa no momento da compra, mas acho que de próxima compro em fita, pois o trabalho de soldar cada um deles não é fácil. 

No final acabei por ligar só 10 para testar, com o STM8S.

O resultado foi otimo.

O processo de por os Leds a funcionar com o STM8S também não foi muito fácil, por isso partilho o código final, para poupar tempo a quem queira utilizar o STM8S para controlar estes Leds.

É tudo uma questão de acertar com o timing dos sinais enviados para os Leds…

WS2812B_1WS2812B_2

Este foi a primeira tentativa de soldar os Leds.

E aqui este o código :

/* MAIN.C file
 * 
 * STM8S
 * Drive RGB Led WS2812B
 *
 * Copyright (c) 2016 joaquim.org
 */

#include "stm8s.h"
#include "delay.h"


#define NB_LEDS 10
unsigned char LedsArray[NB_LEDS*3];
unsigned int nbLedsBytes = NB_LEDS*3;

typedef struct {
  unsigned char R;
  unsigned char G;
  unsigned char B;
} RGBColor;

const RGBColor RED = {255,0,0};
const RGBColor GREEN = {0,255,0};
const RGBColor BLUE = {0,0,255};
const RGBColor BLACK = {0,0,0};
const RGBColor WHITE= {255,255,255};


#define	ANIMATIONS 18
const unsigned char LedAnimation[ANIMATIONS][NB_LEDS] = 
	{
		{ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 },
		{ 01, 00, 00, 00, 00, 00, 00, 00, 00, 00 },
		{ 01, 01, 00, 00, 00, 00, 00, 00, 00, 00 },
		{ 01, 01, 01, 00, 00, 00, 00, 00, 00, 00 },
		{ 01, 01, 01, 01, 00, 00, 00, 00, 00, 00 },
		{ 01, 01, 01, 01, 01, 00, 00, 00, 00, 00 },
		{ 00, 01, 01, 01, 01, 01, 00, 00, 00, 00 },
		{ 00, 00, 01, 01, 01, 01, 01, 00, 00, 00 },
		{ 00, 00, 00, 01, 01, 01, 01, 01, 00, 00 },
		{ 00, 00, 00, 00, 01, 01, 01, 01, 01, 00 },
		{ 00, 00, 00, 00, 00, 01, 01, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 01, 01, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 01, 01, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 01, 01, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 00, 01, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 00, 00, 01, 01, 01 },
		{ 00, 00, 00, 00, 00, 00, 00, 00, 01, 01 },
		{ 00, 00, 00, 00, 00, 00, 00, 00, 00, 01 },		
	};


unsigned char stepUp = 0;
unsigned char stepDir = 0;
unsigned char stepColor = 0;

void SetLedColor(unsigned char LedId, unsigned char R, unsigned char G, unsigned char B)
{
  LedsArray[LedId*3] = G;
  LedsArray[LedId*3+1] = R;
  LedsArray[LedId*3+2] = B;
}

void SetLedColors(unsigned char LedId,RGBColor Color) {
  LedsArray[LedId*3] = Color.G;
  LedsArray[LedId*3+1] = Color.R;
  LedsArray[LedId*3+2] = Color.B;
}


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

void SendLedsArray( void )
{

	// Base Code From : https://github.com/wassfila/STM8_IoT_HelloWorld
  #asm
			lb_intiLoop:                          
				LDW			X,						0x0
				
			lb_begin_loop:                        
				LD      A,           	(_LedsArray,X)
				LDW			Y,					 	#0x8
				
			; send bit -----------------------------------------        
      lb_start_bit:   
				BSET    0x500F,    		#0x7
				SLL			A
        JRNC    lb_bit_Send_0      		
				
			lb_bit_Send_1:  
				NOP
				NOP
				NOP
				NOP
				NOP
				NOP			
				NOP
				NOP
				NOP
				NOP
				NOP
				NOP					
        BRES    0x500F,      	#0x7  
				NOP
				JRA     lb_next_bit

			lb_bit_Send_0: 
				NOP
        BRES    0x500F,      	#0x7
				NOP
				NOP
				NOP
				NOP
				NOP
				
			lb_next_bit:
				DECW		Y
				JRNE    lb_start_bit
				
			lb_nex_led:
        INCW		X 
				CPW			X,						_nbLedsBytes
        JRC   	lb_begin_loop                   										
				
			lb_exit:
				nop
#endasm				
  
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

RGBColor getColor( unsigned char colorID ) {
	
	if ( colorID == 0 )	return BLACK;
	colorID = stepColor;
	if ( colorID == 1 )	return WHITE;
	if ( colorID == 2 )	return RED;
	if ( colorID == 3 )	return GREEN;
	if ( colorID == 4 )	return BLUE;	
	return BLUE;
}

void doAnimation( void ) {
	
	unsigned char i;
	RGBColor Color;
	
	for (i = 0; i < NB_LEDS; i++) {		
		Color = getColor(LedAnimation[stepUp][i]);
		SetLedColors(i, Color);		
	}
	
	stepUp++;
	
	if (stepUp >= ANIMATIONS) {
		stepUp = 0;
		stepColor++;
		if ( stepColor > 4) stepColor = 1;
	}

	SendLedsArray();
	_delay_ms(300);		
}



main() {	

	unsigned char i;
	
	// Initialise the clock to have a /1 prescaler and use the external crystal clock source for accuracy.
	CLK_DeInit();
	CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
	CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
	
	// -------------------------------------------------------------------------
	//Debug LED	
	// Reset ("de-initialise") GPIO port D.
	GPIO_DeInit(GPIOD);
	// Initialise pin 0 of port D by setting it as:
	// - an output pin,
	// - using a push-pull driver,
	// - at a low logic level (0V), and
	// - 10MHz.
	GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_FAST);
	GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_LOW_FAST);
	GPIO_WriteLow(GPIOD, GPIO_PIN_0);
	GPIO_WriteLow(GPIOD, GPIO_PIN_7);
	
	// Turn OFF all LEDs
	for (i = 0; i < NB_LEDS; i++) {
		SetLedColor(i, 0, 0, 0);
	}
		
	// Infinite loop.
	for(;;) {

		// Blink Debug LED		
		GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
		
		doAnimation();
		
	}
}