Viva a todos,
como estamos em época Natalícia, lembrei-me de ajeitar rapidamente um simulador de velas, pois por aqui gostamos bastante de as ter espalhadas pela casa... e assim, em formato electrónico, fica ambientalmente mais sustentavel.
Procurei por componentes há muito esquecidos nas caixas, e que certamente não iriam ver a luz de outra maneira, e fiz rápido dois códigos para um PIC10F200 e para um PIC16F.
Não fiz ainda para um ATtiny porque não tenho cá nenhum à mão, mas logo virá.
Espero que gostem e que vos ajude a limpar as gavetas, tal como a mim
Código para o PIC10F200, todas as saídas estão com LED ::
/*
* Candle Simulator
* This code simulates the behaviour of a candle, using LEDs and a PIC10F200 microcontroller.
* No interrupts are used, only TMR0 counter.
*
* Author: Antonio Sergio Sena
* email: a.s.sena@gmail.com
* December 2011
*
* Based on the work of Joao Figueiredo, www.enide.net
*
*
*/
#include <htc.h>
/*********************************************************************************************************
*
* Definitions
*
*********************************************************************************************************/
// FUSES definition
__CONFIG (MCLREN & WDTDIS & UNPROTECT);
// Function Definition
unsigned char getRandomBit(void);
// Variable definitions
unsigned char i=15, resto_i;
unsigned int Random_TimerCounter=0;
struct{
unsigned Duty_Cycle:1;
}FLAGS;
/*********************************************************************************************************
*
* Main program
*
*********************************************************************************************************/
void main (void)
{
// Turn off analogue comparators
#if defined(_10F204) || defined(_10F206)
CMCON = 0; // Analogue comparator OFF
#endif
// Configure IN/OUT
GPIO = 0;
TRIS = 0b00001000;
GPIO = 0;
// Configure TMR0 and prescaller
OPTION = 0b11000111; // TMR0 1:256
TMR0 = 217; // 100Hz period (37 is the value to get 100Hz)
// Main infinite loop
while (1)
{
// Wait until TMR0 overflows
if (TMR0 == 1) // Checking for TMR0=0 will reset Prescaller
{
switch (FLAGS.Duty_Cycle)
{
case 0:
GPIO = 0; // Pins OFF
TMR0 = 256-resto_i; // Duty-Cycle OFF
FLAGS.Duty_Cycle = 1; // Invert Flag
break;
case 1:
GPIO = 0x07; // Pins ON
TMR0 = 256-i; // Duty-cycle ON time
resto_i = 50-i; // Prepare for Duty-Cycle OFF time
FLAGS.Duty_Cycle = 0; // Invert Flag
break;
default:
FLAGS.Duty_Cycle = 0; // Error: force to ZERO
break;
}
}
Random_TimerCounter++; // Increment Random Generator Timer-Counter
if (Random_TimerCounter > 6000) // Is time to Generate Random number ?
{
Random_TimerCounter = 0; // Clear Random Generator Timer-Counter
if(getRandomBit()) // Get new random value
i+=3; // if bit is 1 increment
else
i-=3; // if bit is 0 decrement
// Keep i within 0..100 limits
if( i<20 ) i=20; // not too low so the LED doesn't go off completely
if( i>49 ) i=49; // not too high to obfuscate the surroundings
}
}
}
/*********************************************************************************************************
*
* Main program - END
*
*********************************************************************************************************/
/*********************************************************************************************************
*
* Functions
*
*********************************************************************************************************/
// Generate Random bit, based on the 1+x10+x11 polynomial function
unsigned char getRandomBit(void)
{
static unsigned int shiftregister = 0x9500;
unsigned int value;
unsigned char output;
// Feedback based on 1+x10+x11 polynomial function
// value = (shiftregister&0x0200)>>9 ^ (shiftregister&0x0400)>>10; // Cant compute this, have to divide in two expressions
value = (shiftregister&0x0400)>>10;
value = (shiftregister&0x0200)>>9 ^ value;
// Feedback
shiftregister <<= 1;
shiftregister |= value;
output = (value^1) & 0x01;
return output;
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
O código para o PIC16F, as saídas são RA0..3 ::
/*
* Candle Simulator
* This code simulates the behaviour of a candle, using LEDs and a PIC16F microcontroller.
* No interrupts are used, only TMR0 counter.
*
* Author: Antonio Sergio Sena
* email: a.s.sena@gmail.com
* December 2011
*
* Based on the work of Joao Figueiredo, www.enide.net
*
*
*/
#include <htc.h>
/*********************************************************************************************************
*
* Definitions
*
*********************************************************************************************************/
// FUSES definition
__CONFIG (PROTECT & CPD & LVPDIS & BOREN & MCLREN & PWRTEN & WDTDIS & INTIO);
// Function Definition
unsigned char getRandomBit(void);
// Variable definitions
unsigned char i=15, resto_i;
unsigned int Random_TimerCounter=0;
struct
{
unsigned Duty_Cycle:1;
}FLAGS;
/*********************************************************************************************************
*
* Main program
*
*********************************************************************************************************/
void main (void)
{
// Configure IN/OUT
PORTA = 0;
PORTB = 0;
TRISA = 0;
TRISB = 0;
PORTA = 0;
PORTB = 0;
// Turn off analogue comparators
CMCON = 0x07;
// Configure TMR0 and prescaller, no interrupt
OPTION = 0b00000111; // TMR0 1:256
TMR0 = 217; // 100Hz period (37 is the value to get 100Hz)
T0IF = 0; // Clear TMR0 flag
T0IE = 0; // No TMR0 interrupt
// Main infinite loop
while (1)
{
// Wait until TMR0 overflows, by checking TMR0 interrupt flag
if (T0IF)
{
T0IF = 0; // Clear TMR0 flag
// Check in which cycle is it - 0:OFF-cycle, 1:ON-cycle
switch (FLAGS.Duty_Cycle)
{
case 0:
PORTA = 0; // Pin OFF
TMR0 = 256-resto_i; // Duty-Cycle OFF
FLAGS.Duty_Cycle = 1; // Invert Flag
break;
case 1:
PORTA = 0x0F; // Pin ON
TMR0 = 256-i; // Duty-cycle ON time
resto_i = 50-i; // Prepare for Duty-Cycle OFF time
FLAGS.Duty_Cycle = 0; // Invert Flag
break;
default:
FLAGS.Duty_Cycle = 0; // Error: force to ZERO
break;
}
}
Random_TimerCounter++; // Increment Random Generator Timer-Counter
if (Random_TimerCounter > 6000) // Is time to Generate Random number ?
{
Random_TimerCounter = 0; // Clear Random Generator Timer-Counter
if(getRandomBit()) // Get new random value
i+=3; // if bit is 1 increment (these may be changed to have a steep step)
else
i-=3; // if bit is 0 decrement
// Keep i within 0..100 limits
if( i<20 ) i=20; // not too low so the LED doesn't go off completely
if( i>49 ) i=49; // not too high to obfuscate the surroundings
}
}
}
/*********************************************************************************************************
*
* Main program - END
*
*********************************************************************************************************/
/*********************************************************************************************************
*
* Functions
*
*********************************************************************************************************/
// Generate Random bit, based on the 1+x10+x11 polynomial function
unsigned char getRandomBit(void)
{
static unsigned int shiftregister = 0x9500;
unsigned int value;
unsigned char output;
// Feedback based on 1+x10+x11 polynomial function
value = (shiftregister&0x0200)>>9 ^ (shiftregister&0x0400)>>10;
// Feedback
shiftregister <<= 1;
shiftregister |= value;
output = (value^1) & 0x01;
return output;
}