User Tools

Site Tools


projects:gradateur_pour_bande_de_leds_12v:home

Gradateur pour bande de leds 12v

~~META:description abstract=Gradateur PWM pour bande de leds 12v, max env. 7A~~

Basé sur micro-contrôleurs avec télécommande radio, éventuellement avec récepteurs multiples.

Features

  • Gradation de 0 à 100% de un ou plus récepteurs par ondes radio
  • Taille réduite
  • Peu onéreux

Protocole

Frames de 2 octets :

[0 ADDR:3 OUT:1 PARAM:3] [1 VALUE:7]

Cela autorise au max 8 caneaux avec 2 sorties chacuns, pour lesquelles on peut avoir 8 paramètres prennants 128 valeurs …

Ex de paramètres : le mode (fixe, musique …), le niveau d'allumage (0-127) …

Nom du paramêtre Code du paramêtre Signification des valeurs
Mode 0 0 : mode fixe
1 : mode réactif au son
Valeur fixe 1 0-127 : niveau de luminosité du mode fixe

Ex :

0100000 0000000 Passage en mode fixe de la sortie 0 du récepteur 2
000X000 0000001 Passage en mode son de toutes les sorties de tous les récepteurs (le broadcast touche tout)

Télécommande

  • Base d'ATMega8L cadencé à 1MHz (8MHz interne et prescaler par 8)
  • Alimentation par pile CR2032 (3V)
  • Pad tactile de nintendo ds avec détecteur de contact pour gérer un mode veille
  • Leds de feedback (vertes et/ou rouges, limité par l'alim 3V)
  • Emetteur 433MHz OOK qui doit être coupé quand il n'y a aucun ordre à transmettre
  • Modes recipient/broadcast, frames de plus de 1 octet

Coté consommation en fonctionnement le micro tourne autour de 1-3mA, en veille on descent vers le µA.

Le cadencement à 1MHz parait bas mais il divise la consommation par plus de 2 (pas de quartz externe et rythme lent). Dans ces conditions on peut avoir une liaison série à 4800 bauds soit 436 octets/sec (on peut descendre à 240bauds) et une analyse du pad tactile à 4800 ou 9600 par secondes …

On peut avoir pas mal de leds en multiplexant (une par bouton virtuel ?), faire attention ça pompe du jus … Les leds 0805 sont déjà bien lumineuses à 1mA ça doit permettre d'en mettre un certain nombre et comme le but est de souligner plutôt que d'éclairer …

Schéma

controller.svg

BOM

Dsn. Qt P (USD ct)
Total

PCB

Récepteur

  • Base d'ATMega8L cadencé à 8MHz, ici on s'en fout de gagner 2mA de conso …
  • Courant en sortie supérieur à 3A, commutation par MOS, prévoir l'emplacement pour 2 sorties même si non-peuplées ?
  • Alimentation 12V
  • Au moins 50fps
  • Prévoir un capteur de son pour le fun. ^^

Schéma

receiver.svg

BOM

Dsn. Qt P (USD ct)
R 100 1/2 0.3/0.6
R 2k7 1 0.3
R 10k 2 0.6
R 100k 3 0.9
C 22p 2 1
C 10n 1 0.5
C 100n 2 1
C 330n 1 0.5
C 1u 1 0.5
C 10u/10V 1 stock
C 220u/16V 1 stock
1N4148 1 2
MMBTA3904 1 4
AP4800 1/2 14/28
Quartz 8MHz 1 25
Micro electret 1 75
78M05 1 15
ATMega8L 1 90
Recepteur radio 1 75
Bornier 1-3 18-54
Connecteur adresse 1 stock
Connecteur ISP 1 3
PCB 16cm2 22
Total env 3.5-4USD

PCB

Dimensions réelles 51x31mm ! (image en 600 dpi)

Implantation récepteur

Typon récepteur

Fichier WinTypon

Analyse thermique

On considère que la température ne doit pas dépasser 70°C. Vu le circuit la résistance thermique doit être entre 125 et 50 °C/W (on à des zones de cuivre pour dissiper mais quand même pas 6.5cm2, cf plus haut), prenons 90°C/W.

L'élévation max est de 30°C (T ambiante max 40°C), donc la puissance dissipée max est de 330mW.

Pour 2 sorties ça fait 166mW par mos ce qui nous donne un max de 3A par mos.

Pour un seul mos ça fait 4.3A.

Dans ce cas on aurait un max de 7.5m de bande par mos si 2 mos utilisés et 10.75m de bande sur un seul mos.

Mettre un bout d'alu sur les mos n'est pas obligatoire mais ça ne fera qu'améliorer les choses … (yep ! ^^)

Firmware

main.c
//==========================================================================
// Project: Radio controlled dual 1 color led strip driver with sound sensor
// Type: firmware
// Name: main.c
// Author: Etienne Meleard
// Creation Date: 2013-02-01
// Tabsize: 4
//==========================================================================
 
 
//============================== WARNING ==================================//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
//                                                                         //
// Fuses must be like SUT1 = 1, SUT0 = 1, CKSEL3 = 1, CKSEL2 = 0,          //
// CKSEL1 = 0 and CKSEL0 = 0 to ensure µC is using the crystal as clock    //
// (otherwise it uses the 8MHz internal clock), full swing mode is         //
// mandatory to acheive 8MHz operation.                                   //
//                                                                         //
// CKDIV8 fuse must not be set to avoid clock frequency divided by 8       //
//                                                                         //
// Fuse set or = 1 means checked in ponyprog                               //
//                                                                         //
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
//=========================================================================//
 
 
// ================= Fuses ================= //
 
/*FUSES = { // No success writing fuse this way, command line below ...
	.low = (FUSE_SUT1 & FUSE_SUT0 & FUSE_CKSEL3),
	.high = HFUSE_DEFAULT,
	.extended = EFUSE_DEFAULT,
};*/
// Run avrdude -c usbasp -p m8 -U lfuse:w:0xc7:m -U hfuse:w:0xdf:m at first (-F may be needed)
 
 
// ================ Includes =============== //
 
#include <avr/io.h>
#include <sup_avr/io2.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
 
// ================ Pinouts ================ //
 
#define RX			PORTD.bit0
#define RX_COMPLETE	SIG_USART_RECV
 
#define SOUND_ADC	7
 
#define ADDR0		PORTD.bit5
#define ADDR1		PORTD.bit6
#define ADDR2		PORTD.bit7
 
#define EVAL_STATE	TIMER0_OVERFLOW
 
#define OUT0		PORTB.bit1
#define LVL0		OCR1A
#define OUT1		PORTB.bit2
#define LVL1		OCR1B
 
#define LED			PORTD.bit4
#define BLINK LED=1; _delay_ms(150); BLINK LED=0; _delay_ms(150)
 
#define SDA			PORTC.bit4
#define SCL			PORTC.bit5
 
 
// ================ Globals ================ //
 
#define MODE	0
	#define MODE_FIXED 0
	#define MODE_SOUND 1
#define FIXED_VALUE	1
#define FOO		2
// Must be big enough for 2 times the params
volatile uint8_t params[16] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
 
volatile uint8_t addr = 0x00;
volatile uint16_t rxbyte = 0x0000;
volatile uint8_t received = 0x00;
 
 
// ================ Functions ============== //
 
void init(void) {
	// USART
	UCSRA = 0x00;
	UCSRB = 0x90;	// Rx enable and Rx irq enable
	UCSRC = 0xa6;	// 8 bits, 1 stop bit, even parity
	UBRR = 103;		// 4800 baud
 
	// ADC (sound sensor)
	ADMUX = 0x00 | SOUND_ADC;	// Ext ref and channel
	ADCSRA = 0xef;				// Enable, start, free running, irq enable, prescaler=128 : 4807conv/s
 
	// Address inputs
	DDRD &= 0x1f;
	PORTD |= 0xe0;	// Pull-up
 
	// State timer
	TCCR0 = 0x05;	// Prescaler=1024 : 30irq/s
	TIMSK |= 0x01;	// Irq enable
 
	// Outputs
	DDRB |= 0x06;
 
	// PWM Timer
	TCCR1A = 0xa1;	// Phase and frequency correct PWM
	TCCR1B = 0x14;	// mode, prescaler=256 : 122Hz
	ICR = 0x007f;	// 128  levels
 
	// Led
	DDRB |= 0x10;
 
	// I2C
	DDRC |= 0x30;
}
 
// Read params from EEPROM
void loadParams(void) {
	uint8_t param;
	for(param=0; param<16; idx++) {
		while(EECR & (1<<EEWE));
		EEAR = param;
		EECR |= (1<<EERE);
		params[param] = EEDR;
	}
}
 
// Save new param value into EEPROM
void writeParam(uint8_t param, uint8_t value) {
	while(EECR & (1<<EEWE));
	EEAR = param;
	EEDR = value;
	EECR |= (1<<EEMWE);
	EECR |= (1<<EEWE);
}
 
// Eval the state of one output
void evalState(uint8_t output) {
	uint8_t offset = 0;
 
	if(output) offset = 8;
	output = output ? *LVL1 : *LVL0;
 
	switch(params[offset + MODE]) {
		case MODE_FIXED :
			output = params[offset + FIXED_VALUE];
			break;
		case MODE_SOUND :
			output = 1.7 * (ADC - 184);				// TODO : measure idle value and evaluate sensitivity or make it a parameter
			break;
	}
}
 
 
// =============== Interrupts ============== //
 
SIGNAL(RX_COMPLETE) {
	uint8_t rxaddr, p, v;
	if(UDR & 0x80) {								// byte 1
		if(rxbyte) {								// already got byte 0
			rxaddr = (rxbyte & 0x0070) >> 4;
			if(rxaddr && (rxaddr != addr)) return;	// not for me
			p = rxbyte & 0x000f;					// get param index with out multiplier
			v = UDR & 0x7f;							// get value
			params[p] = v;							// set param
			writeParam(p, v);						// save param for future restarts
			if(!rxaddr) {							// if broadcast value must be set for both outputs
				params[8 + p] = v;
				writeParam(8 + p, v);
			}
 
			rxbyte = 0x0000;
			received = 1;							// signal rx
		}											// else we just had a second byte without the first one, we discard it
	}else rxbyte = 0xff00 + UDR;					// byte 0
}
 
SIGNAL(EVAL_STATE) { // 30Hz
	evalState(0);
	evalState(1);
}
 
 
// ================== Main ================= //
 
int main(void) {
	uint8_t a;
 
	cli();		// WatchDog disabled AT ALL TIMES !
	init();
	loadParams();
	sei();
 
	BLINK;
	BLINK;
 
	while(1) {
		if(received) {		// Signal received byte
			received = 0;
			BLINK;
		}
 
		// Get addr
		a = 0x00;
		if(!ADDR0) a += 1;
		if(!ADDR1) a += 2;
		if(!ADDR2) a += 4;
		addr = a;
 
		_delay_ms(10);
	}
 
	return 0;
}
Makefile
# Name: Makefile
# Author: Etienne Meleard
# Creation Date: 2013-02-01
# Tabsize: 4
 
DEVICE  = atmega8
F_CPU   = 8000000	# in Hz
FUSE_L  = # see below for fuse values for particular devices
FUSE_H  = 
AVRDUDE = avrdude -c usbasp -p $(DEVICE) # edit this line for your programmer
 
CFLAGS  = -I. -DDEBUG_LEVEL=0
OBJECTS = main.o
 
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
 
##############################################################################
# Fuse values for particular devices
##############################################################################
# If your device is not listed here, go to
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi
# and choose options for external crystal clock and no clock divider
#
################################## ATMega8 ##################################
# ATMega8 FUSE_L (Fuse low byte):
# 0x9f = 1 0 0 1   1 1 1 1
#        ^ ^ \ /   \--+--/
#        | |  |       +------- CKSEL 3..0 (external >8M crystal)
#        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
#        | +------------------ BODEN (BrownOut Detector enabled)
#        +-------------------- BODLEVEL (2.7V)
# ATMega8 FUSE_H (Fuse high byte):
# 0xc9 = 1 1 0 0   1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
#        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
#        | | | |   | +-------- BOOTSZ1
#        | | | |   + --------- EESAVE (don't preserve EEPROM over chip erase)
#        | | | +-------------- CKOPT (full output swing)
#        | | +---------------- SPIEN (allow serial programming)
#        | +------------------ WDTON (WDT not always on)
#        +-------------------- RSTDISBL (reset pin is enabled)
#
############################## ATMega48/88/168 ##############################
# ATMega*8 FUSE_L (Fuse low byte):
# 0xdf = 1 1 0 1   1 1 1 1
#        ^ ^ \ /   \--+--/
#        | |  |       +------- CKSEL 3..0 (external >8M crystal)
#        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
#        | +------------------ CKOUT (if 0: Clock output enabled)
#        +-------------------- CKDIV8 (if 0: divide by 8)
# ATMega*8 FUSE_H (Fuse high byte):
# 0xde = 1 1 0 1   1 1 1 0
#        ^ ^ ^ ^   ^ \-+-/
#        | | | |   |   +------ BODLEVEL 0..2 (110 = 1.8 V)
#        | | | |   + --------- EESAVE (preserve EEPROM over chip erase)
#        | | | +-------------- WDTON (if 0: watchdog always on)
#        | | +---------------- SPIEN (allow serial programming)
#        | +------------------ DWEN (debug wire enable)
#        +-------------------- RSTDISBL (reset pin is enabled)
#
############################## ATTiny25/45/85 ###############################
# ATMega*5 FUSE_L (Fuse low byte):
# 0xef = 1 1 1 0   1 1 1 1
#        ^ ^ \+/   \--+--/
#        | |  |       +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
#        | |  +--------------- SUT 1..0 (BOD enabled, fast rising power)
#        | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
#        +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
# ATMega*5 FUSE_H (Fuse high byte):
# 0xdd = 1 1 0 1   1 1 0 1
#        ^ ^ ^ ^   ^ \-+-/ 
#        | | | |   |   +------ BODLEVEL 2..0 (brownout trigger level -> 2.7V)
#        | | | |   +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved)
#        | | | +-------------- WDTON (watchdog timer always on -> disable)
#        | | +---------------- SPIEN (enable serial programming -> enabled)
#        | +------------------ DWEN (debug wire enable)
#        +-------------------- RSTDISBL (disable external reset -> enabled)
#
################################ ATTiny2313 #################################
# ATTiny2313 FUSE_L (Fuse low byte):
# 0xef = 1 1 1 0   1 1 1 1
#        ^ ^ \+/   \--+--/
#        | |  |       +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
#        | |  +--------------- SUT 1..0 (BOD enabled, fast rising power)
#        | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
#        +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
# ATTiny2313 FUSE_H (Fuse high byte):
# 0xdb = 1 1 0 1   1 0 1 1
#        ^ ^ ^ ^   \-+-/ ^
#        | | | |     |   +---- RSTDISBL (disable external reset -> enabled)
#        | | | |     +-------- BODLEVEL 2..0 (brownout trigger level -> 2.7V)
#        | | | +-------------- WDTON (watchdog timer always on -> disable)
#        | | +---------------- SPIEN (enable serial programming -> enabled)
#        | +------------------ EESAVE (preserve EEPROM on Chip Erase -> not preserved)
#        +-------------------- DWEN (debug wire enable)
 
 
# symbolic targets:
help:
	@echo "This Makefile has no default rule. Use one of the following:"
	@echo "make hex ....... to build main.hex"
	@echo "make program ... to flash fuses and firmware"
	@echo "make fuse ...... to flash the fuses"
	@echo "make flash ..... to flash the firmware (use this on metaboard)"
	@echo "make clean ..... to delete objects and hex file"
 
hex: main.hex
 
program: flash
 
# rule for uploading firmware:
flash: main.hex
	$(AVRDUDE) -U flash:w:main.hex:i
 
# rule for deleting dependent files (those which can be built by Make):
clean:
	rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o main.s
 
# Generic rule for compiling C files:
.c.o:
	$(COMPILE) -c $< -o $@
 
# Generic rule for assembling Assembler source files:
.S.o:
	$(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
 
# Generic rule for compiling C to assembler, used for debugging only.
.c.s:
	$(COMPILE) -S $< -o $@
 
# file targets:
 
main.elf: $(OBJECTS)
	$(COMPILE) -o main.elf $(OBJECTS)
 
main.hex: main.elf
	rm -f main.hex main.eep.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
	avr-size main.hex
 
# debugging targets:
 
disasm:	main.elf
	avr-objdump -d main.elf
 
cpp:
	$(COMPILE) -E main.c

Discussion

~~CHAT~~

projects/gradateur_pour_bande_de_leds_12v/home.txt · Last modified: 2022/06/30 21:13 by 127.0.0.1