Paweł Kardaś
Published

Magic Hercules - driver for digital LEDs

MH is a beginner-friendly SPI driver for digital LED strips such as WS2812, etc. Lighting projects have never been so easy!

BeginnerWork in progress1 hour589
Magic Hercules - driver for digital LEDs

Things used in this project

Hardware components

Arduino Mega 2560
Arduino Mega 2560
One of the platforms on which the Magic Hercules module was tested - Arduino C ++
×1
ATB Andromeda 1.05a
Atnel Development Board 1.05a - One of the platforms with which the Magic Hercules module was tested - C for AVR
×1
STM32 Nucleo-64 Board
STMicroelectronics STM32 Nucleo-64 Board
One of the platforms on which the Magic Hercules module was tested - C for ARM/STM
×1
Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
One of the platforms on which the Magic Hercules module was tested - Python for Raspberry Pi
×1

Story

Read more

Schematics

Magic Hercules Module in DIP8 package board

The MH module is a board with the dimensions of a standard DIP8 package.

MH module as schematic element

The Magic Hercules module can be used both on the breadboard and in your own PCB. Pins 6 and 7 of the SPI bus are +3.3 V tolerant. Pin 1 is used to define the type of the tested magic LED strip - RGB (3 bytes) or RGBW (4 bytes). Pin 5 is an output that connects to the digital LED input. The +5 V power supply should be properly connected to pins 4 and 8.

Code

Raspberry Pi - Python

Python
The C source code has been ported to Python for use with Raspberry Pi.
import spidev
from time import *

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 800000 # 800 kHz

rgb = 3
led_count = 24

mbuf = [[0] * rgb for i in range(led_count)]
spibuf = [0] * 72

# LED start indexes
ir = 0
ig = 8
ib = 16

# Convert 2D mbuf to 1D spibuf
def buf_convert():
    idx = 0
    for list in mbuf:
        for x in list:
            spibuf[idx] = x
            idx += 1

def draw_stargate():
    
    global ir
    global ig
    global ib
 
    for i in range(24):
        for j in range(3):
            mbuf[i][j] = 0
                  
    buf_convert()
    spi.writebytes(spibuf)
    
    mbuf[3] = [0,0,5]
    mbuf[9] = [0,0,5]
    mbuf[15] = [0,0,5]
    mbuf[21] = [0,0,6]
    
    mbuf[ir][1] = 5
    mbuf[ig][0] = 5
    mbuf[ib][0] = 3
    mbuf[ib][1] = 5
    
    ir = ir + 1
    if ir == 24:
        ir = 0
        
    ig -= 1
    if ig < 0:
        ig = 23
        
    ib += 1
    if ib == 24:
        ib = 0
    
    buf_convert()
    spi.writebytes(spibuf)
    

while True:
    
    draw_stargate()
    sleep(0.05)

AVR - C source

C/C++
Originally developed C source code for AVR microcontrollers - simple stargate effect.
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>

#include "MK_HERCULES_SPI/mk_hercules_spi.h"

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

TRGB mbuf[24];

int ir=0, ig=8, ib=16;

void draw_stargate( void ) {

	mbuf[ir].r = 5;
	mbuf[ig].g = 5;
	mbuf[ib].r = 5; mbuf[ib].g = 3;

	if( ++ir == 24 ) ir = 0;
	if( --ig < 0 ) ig = 23;
	if( ++ib == 24 ) ib = 0;

	mbuf[3].b = 10;
	mbuf[9].b = 10;
	mbuf[15].b = 10;
	mbuf[21].b = 10;

	hspi_send_buf( mbuf, 24*3 );
	memset( mbuf, 0, 24*3 );
}


int main( void ) {

	hspi_init();

	while(1) {

		draw_stargate();
		_delay_ms(50);

	}
}

Arduino - C++ source

C/C++
Source code with the Stargate effect ported to the Arduino C ++ platform
#include <SPI.h>

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

TRGB mbuf[24];

int ir=0, ig=8, ib=16;

void setup() {
  SPI.begin();
  SPI.setClockDivider( SPI_CLOCK_DIV32 );
}

void draw_stargate() {

  memset( mbuf, 0, sizeof(mbuf) );
  
  mbuf[ir].r = 5;
  mbuf[ig].g = 5;
  mbuf[ib].r = 5; mbuf[ib].g = 3;

  if( ++ir == 24 ) ir = 0;
  if( --ig < 0 ) ig = 23;
  if( ++ib == 24 ) ib = 0;

  mbuf[3].b = 10;
  mbuf[9].b = 10;
  mbuf[15].b = 10;
  mbuf[21].b = 10;

  cli();
  SPI.transfer( mbuf, sizeof(mbuf) );
  sei();
}

void loop() {
  draw_stargate();
  delay(50);
}

ARM/STM - C

C/C++
Thanks to the SPI used, the code can be used on ANY STM microcontroller (for example, on Nucleo like, Discovery, etc. boards).
/* USER CODE BEGIN Header */
/**
  **************************
  * @file           : main.c
  * @brief          : Main program body
  **************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  **************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <string.h>

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_tx;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_SPI1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */


// new TRGB type
typedef struct {
	uint8_t g;
	uint8_t r;
	uint8_t b;
} TRGB;

// Magic LED RING - 24 LEDs
TRGB mbuf[24];	// FX buffer


// LED start indexes
int ir=0, ig=8, ib=16;


void draw_stargate( void ) {

	// clear FX buffer
	memset( mbuf, 0, 24*3 );

	// moving lights
	mbuf[ir].r = 5;
	mbuf[ig].g = 5;
	mbuf[ib].r = 5; mbuf[ib].g = 3;

	// change moving lights position
	if( ++ir == 24 ) ir = 0;
	if( --ig < 0 ) ig = 23;
	if( ++ib == 24 ) ib = 0;

	// 4 blue light
	mbuf[3].b = 10;
	mbuf[9].b = 10;
	mbuf[15].b = 10;
	mbuf[21].b = 10;

	// send FX buffer via SPI to Magic HERCULES
	HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)mbuf, 72 );
}



/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  draw_stargate();
	  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	  HAL_Delay(50);

  }
  /* USER CODE END 3 */
}

Credits

Paweł Kardaś

Paweł Kardaś

1 project • 0 followers
I am a hobbyist about electronics and embedded programming. As an engineer, I work with Atnel (PCB & 3D design, prog. & writing)

Comments