Ce site contient essentiellement des notes de travail. Le contenu est en constante évolution, et loin d'être achevé. (+ d'infos)
La plupart des documentations informatiques sont orientées Debian / Ubuntu.
Electronique/Projets/RC-LedLights - Jeu de LEDs pour modèle réduit (PIC)
< Electronique | Projets
Sauter à la navigation
Sauter à la recherche
Introduction
Ce projet consiste à commander 4 voies de LED depuis une voie du récepteur d'un modèle réduit. Les voies de LEDs sont les suivantes:
- GLOW (s'allume et s'éteint gentiment)
- FLASH
- PLAIN1 (ON/OFF)
- PLAIN2 (ON/OFF)
Chaque voie de LED peut être réglée pour s'allumer à une position différente de la voie du récepteur.
- Vidéo de démonstration (Xvid)
- RC-LedLights.zip - HEX binaire (PIC 12F629)
Schéma
Code
/*
* Filename: lights1.c
* Language: C (CCS PCWHD 4.x)
* Date: 2010-02-28
* Version: 1.0
* Author: Jean-Christophe Heger <jcheger*at*ordinoscope*net>
* License: GPLv3 (http://www.gnu.org/copyleft/gpl.html)
*
* GPL means:
* - share it
* - modify it and share your updates
* - keep the names of authors in the header
*
* ... just in case you've forgot to read the GPL license.
*
*
* ==================
* Projet description
* ==================
* This is designed for RC models using receiver channel. Depending on the pulse width, it will
* light up 4 LED channels: GLOW (slowly ~4s), FLASH, PLAIN1 and PLAIN2 (ON/OFF).
*
*
* (-) ----------------o-----o--------------------------------o--------------\
* Receiver (+) ---o------------|-----|------\ | |
* (S) ---|-------\ ##### ##### | | |
* | | # R # # R # | ##################### | |
* | | # 1 # # 2 # \--# Vdd (+) Vss (-) #--/ |
* | | ##### ##### /----# RA5 RA0 #-----------------|-- (GLOW)
* | === \----|-----o----|----# RA4 U1 RA1 #-----\ o-- (-)
* \--o o-------o----------|----# RA3 RA2 #--\ | |
* SW1 | ##################### | \-----------|-- (FLASH)
* | | o-- (-)
* | | |
* | \--------------|-- (PLAIN1)
* R1,R2 - 100 kOhms (pull-down) | o-- (-)
* SW1 - press button | |
* U1 - PIC 12F629 \------------------------------------------|-- (PLAIN2)
* o-- (-)
*
* ======
* Manual
* ======
* By default all LED channels will be up at 1400us. Each can be setup separately.
*
* Press the button for about 2 seconds, and release it. The GLOW LED will light on. Set
* your transmitter at the desired position and press the button. The FLASH LED will light
* on. Do the same and so on. After PLAIN2, it will return at a usual cycle.
*
*/
#include <12f629.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOMCLR
#use delay(clock=4000000)
#define PIN_GLOW PIN_A0
#define PIN_FLASH PIN_A1
#define PIN_PLAIN1 PIN_A2
#define PIN_PLAIN2 PIN_A5
#define PIN_BTN PIN_A3
#define INT_BTN INT_RA3
#define PIN_PWM PIN_A4
#define INT_PWM INT_RA4
#define GLOW_ADDR 0
#define FLASH_ADDR 2
#define PLAIN1_ADDR 4
#define PLAIN2_ADDR 6
// --------------------
// Variable declaration
// --------------------
short btn_state = 0;
long btn_counter = 0;
short glow_state = 0;
long glow_min = -1;
short flash_state = 0;
long flash_counter = 0;
long flash_min = -1;
short plain1_state = 0;
long plain1_min = -1;
short plain2_state = 0;
long plain2_min = -1;
int menu_stage = 0;
long width = 1500; // default width
int offset = 100; // default width offset (anti-glitch)
// --------------------
// Function declaration
// --------------------
void flash ();
void glow ();
void menu ();
void on_off ();
long read16 (int addr);
void read_min ();
void set_state ();
void write16 (int addr, long dbl);
// ---------
// Functions
// ---------
/*
* LED flash function
* @return void
*/
void flash () {
if (flash_state == 0) return;
if (flash_counter == 0) output_low (PIN_FLASH);
flash_counter++;
if (flash_counter > 30) {
output_high (PIN_FLASH);
flash_counter = 0;
}
}
/*
* LED glow function
* @return void
*/
void glow () {
if (glow_state == 0) return;
long i = 0;
while (i < 1000) {
if (glow_state == 1) output_low (PIN_GLOW);
if (glow_state == 1) delay_us (1000-i);
if (glow_state == 1) output_high (PIN_GLOW);
if (glow_state == 1) delay_us (i);
i++;
}
delay_ms (200);
while (i > 0) {
if (glow_state == 1) output_high (PIN_GLOW);
if (glow_state == 1) delay_us (i);
if (glow_state == 1) output_low (PIN_GLOW);
if (glow_state == 1) delay_us (1000-i);
i--;
}
}
/*
* Button menu
* @return void
*/
void menu () {
menu_stage++;
if (menu_stage == 1) { // Menu start
glow_state = 0;
flash_state = 0;
plain1_state = 0;
plain2_state = 0;
output_high (PIN_GLOW);
output_low (PIN_FLASH);
output_low (PIN_PLAIN1);
output_low (PIN_PLAIN2);
}
if (menu_stage == 2) {
glow_min = width - offset;
write16 (GLOW_ADDR, glow_min); // Set glow minimum width
output_low (PIN_GLOW);
output_high (PIN_FLASH);
}
if (menu_stage == 3) {
flash_min = width - offset;
write16 (FLASH_ADDR, flash_min); // Set flash minimum width
output_low (PIN_FLASH);
output_high (PIN_PLAIN1);
}
if (menu_stage == 4) {
plain1_min = width - offset;
write16 (PLAIN1_ADDR, plain1_min); // Set plain1 minimum width
output_low (PIN_PLAIN1);
output_high (PIN_PLAIN2);
}
if (menu_stage == 5) {
plain2_min = width - offset;
write16 (PLAIN2_ADDR, plain2_min); // Set plain2 minimum width
output_low (PIN_PLAIN2);
menu_stage = 0;
}
}
/*
* Activate LED functions if width is above minimum
* @return void
*/
void on_off () {
if (menu_stage > 0) return;
if (width > glow_min) {
glow_state = 1;
} else {
glow_state = 0;
output_low (PIN_GLOW);
}
if (width > flash_min) {
flash_state = 1;
} else {
flash_state = 0;
output_low (PIN_FLASH);
}
if (width > plain1_min) {
plain1_state = 1;
output_high (PIN_PLAIN1);
} else {
plain1_state = 0;
output_low (PIN_PLAIN1);
}
if (width > plain2_min) {
plain2_state = 1;
output_high (PIN_PLAIN2);
} else {
plain2_state = 0;
output_low (PIN_PLAIN2);
}
}
/*
* Read double from EEPROM
* @param int EEPROM base address
* @return long
*/
long read16 (int addr) {
int maj = read_eeprom (addr);
int min = read_eeprom (addr+1);
long dbl = maj * 256 + min;
return dbl;
}
/*
* Read the minimum values from EEPROM and set static variables
* @return void
*/
void read_min () {
glow_min = read16 (GLOW_ADDR);
flash_min = read16 (FLASH_ADDR);
plain1_min = read16 (PLAIN1_ADDR);
plain2_min = read16 (PLAIN2_ADDR);
if (glow_min == -1) { // Set default values on a fresh install
write16 (GLOW_ADDR, 1500 - offset);
glow_min = 1500 - offset;
}
if (flash_min == -1) {
write16 (FLASH_ADDR, 1500 - offset);
flash_min = 1500 - offset;
}
if (plain1_min == -1) {
write16 (PLAIN1_ADDR, 1500 - offset);
plain1_min = 1500 - offset;
}
if (plain2_min == -1) {
write16 (PLAIN2_ADDR, 1500 - offset);
plain2_min = 1500 - offset;
}
}
/*
* Write a double in EEPROM
* @param int EEPROM base address
* @param double Value to write
* @return void
*/
void write16 (int addr, long dbl) {
int maj = dbl / 256;
int min = dbl % 256;
write_eeprom (addr, maj);
write_eeprom (addr+1, min);
}
#INT_RA
/*
* PORTA interrupt
* Read button state and PWM width
* @return void
*/
void ra_isr () {
if (btn_state == 0 && input (PIN_BTN)) { // Button pressed
btn_state = 1;
enable_interrupts (INT_TIMER0);
}
if (input (PIN_PWM)) { // Pulse up
set_timer1(0);
setup_timer_1 (T1_INTERNAL|T1_DIV_BY_1);
}
if (!input (PIN_PWM) && !input (PIN_BTN)) { // Pulse down
long pulse = get_timer1 () - 15;
setup_timer_1 (T1_DISABLED);
if (pulse > 767 && pulse < 2305) {
width = pulse;
on_off ();
}
}
if (btn_state == 1 && !input (PIN_BTN)) { // Button released
btn_state = 0;
if (menu_stage == 0) {
if (btn_counter > 10) menu (); // Menu start
} else {
if (btn_counter >= 1) menu (); // Menu walk
}
btn_counter = 0;
}
}
#INT_TIMER0
/*
* Count how long the button is pressed down and timer for the LED flash function
* @return void
*/
void timer0_isr () {
if (btn_state == 1) btn_counter++;
flash ();
}
void main () {
setup_timer_0 (T0_INTERNAL | T0_DIV_256);
set_timer0 (0);
enable_interrupts (INT_TIMER0);
enable_interrupts (INT_BTN);
enable_interrupts (INT_PWM);
enable_interrupts (GLOBAL);
read_min ();
on_off ();
while (TRUE) {
glow ();
delay_ms (1000);
}
}