Hi all,
I would like to do a LED throwie project using the ATtiny45 or 85. There will be 25 throwies with a LED lighting up at random intervals. My inspiration and starting point is this:
https://github.com/thogo/light-sensity-morse-throwie/blob/master/FireFly-V0.5
The attached swf file is a demonstration/simulation in flash.
Also viewable here: fastSWF - Free Flash and Unity Hosting
I started working on the code and below you can see how far I got. At this moment I have two challenges:
- Generating a random number from 1 to 10 (1,2,3,4,5,6,7,8,9 or 10)
- Making the led blink using PWM (0% to 100% to 0% in one second)
For clarity: a short explanation of what the code should do:
- Generate random number from 1 to 10 (1,2,3,4,5,6,7,8,9 or 10) Let's say 6
- watchdog will timeout every 4 seconds
- count how many times a timeout has occurred
So after 6 timeouts (6x4 = 24 seconds)
- timeout count == random number (6) --> light up LED
- set timeout count to zero
- generate new random, say 3
So after 3 timeouts (3x4 = 12 seconds)
- timeout count == random number (3) --> light up LED
- set timeout count to zero
- generate new random....
There will be 25 throwies running this code
1. Random number
I need this random number to make the LED blink at random intervals. The watchdog will timeout every 4 seconds, after a random number of timeouts the LED blinks. After a blink a new random number will be generated to make the blinking pattern random.
The rand() function is however not so random (explained here). So what I’d like to do is this:
- Use the sensDarkness function in the code
- Say this returns 22816
- Take the last digit, “6” in this case
- This will be my random number
Possible last digits: 0,1,2,3,4,5,6,7,8 or 9
add 1
Result is: 1,2,3,4,5,6,7,8,9 or 10
This is exactly the random range I need
I assume that the sensDarkness function is not that accurate and the last digit will vary
But how does this translate into code ? I’m pretty new to programming in C and would appreciate some hints
2. Make LED blink
I would like to use the PWM on the ATtiny. In about 1 second the LED should go from 0% > 100% > 0%
Does anyone have a link to a usable example of this ?
Thanks for reading !
// for sleep Mode / Powersave we need some additional stuff. Its alredy there,
// if you installed the Attiny extension for Arduino IDE, no additional
// installing needed.
#include <avr/sleep.h>
#include <avr/wdt.h>
// ===========================================================================
// Some definitions for powersave depending of ATTiny type.
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// ---------------------------------------------------------------------------
// LED Pin definitions,
#define LED1_N_SIDE 3
#define LED1_P_SIDE 4
// ===========================================================================
// Variables
// Define light trigger threshold. best way to set it on dusk / dawn level
// diffuse red ones are less sensitive than clear green ones...
int darknessThreshold = 17000;
// Interrupt Flag, should be volatile, means: read from RAM, not register
// because registers are used for interrupt handling, it have to be volatile.
volatile boolean f_wdt = 1;
//Blink interval, holds the number of times a timeout must occur before the LED is blinked
int intBlinkInterval = 5; //??? generate a random number from 1-10 ??? ;
//intTimeOutCount holds the number of occurred timeouts
int intTimeOutCount = 0;
// ===========================================================================
// Setup watchdog
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms, 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
// ===========================================================================
void setup()
{
setup_watchdog(8);
}
// ===========================================================================
// Main
// ===========================================================================
void loop(){
if (f_wdt==1 && sensDarkness(LED1_N_SIDE, LED1_P_SIDE) > darknessThreshold) { // if watchdog timed out AND if it is dark enough
f_wdt=0; // reset watchdog flag
intTimeOutCount++; // increment counter
if (intTimeOutCount == intBlinkInterval){
// reset timeoutcount
intTimeOutCount = 0;
// interval should get a new random value of 1-10
intBlinkInterval = 4; //??? generate a random number from 1-10 ???
// Make LED glow
blink();
}
} //end if wdt and dark
// If no watchdog timout or not dark enough:
// set all used port to intput to save power
pinMode(LED1_N_SIDE,INPUT);
pinMode(LED1_P_SIDE,INPUT);
system_sleep();
} //end loop main
// ===========================================================================
// Subroutines for Sleeping
// ===========================================================================
// set system into the sleep state
// system wakes up when watchdog is timed out
void system_sleep() {
cbi(ADCSRA,ADEN); // switch Analog to Digital converter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
// ----------------------------------------------------------------------------
// Setup for watchdog. Parameter ii for sleeping time:
// 0 = 16ms, 1 = 32ms, 2 = 64ms, 3 = 128ms, 4 = 250ms, 5 = 500ms
// 6 = 1 sec, 7 = 2 sec, 8 = 4 sec,9 = 8 sec
// ----------------------------------------------------------------------------
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
WDTCR |= (1<<WDCE) | (1<<WDE); // start timed sequence
WDTCR = bb; // set new watchdog timeout value
WDTCR |= _BV(WDIE);
}
// -----------------------------------------------------------------------------
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt=1; // set global flag
}
// =============================================================================
// Subroutines for light sensor
// =============================================================================
// Function sensDarkness
// Usage: sensDarkness(Pin-No. N-Side of LED, Pin-No. P-Side of LED):
// will result "darkness-level" - the higher the darker:
// 30000 = pitch black
// 0 = sunshine
int sensDarkness(int LED_N, int LED_P){
unsigned int i; //Parameter bleed-out LED capacitor
// charge the capacitor of LED
pinMode(LED_N,OUTPUT);
pinMode(LED_P,OUTPUT);
digitalWrite(LED_N,HIGH);
digitalWrite(LED_P,LOW);
// Isolate the N end of the diode and turn off internal pull-up resistor
pinMode(LED_N,INPUT);
digitalWrite(LED_N,LOW);
// Count how long it takes the diode to bleed back down to a logic zero
for ( i = 0; i < 30000; i++) {
if ( digitalRead(LED_N)==0) break;
}
// thats it, return result
return i;
}
// =============================================================================
// Make LED glow
// LED should glow from 0 to 100% in 0.5 seconds and back from 100 to 0% in 0.5 seconds
void blink(){
}
Ledfield_Complete.zip (2.4 KB)