The Project:
5" dia circle with 16 5mm leds chasing, 4 (90deg from each other) on at any one time powered by 4 aa batteries. It's controlled by an attiny 825 bootloaded with Arduino. Everything works great. I guy that I'm creating this for now asked if I could add remote on/off functionality. I said I'll look into it.
I found an old tv remote and got the codes using Raw IR Commander from the adafriut.com site.
The Problem:
I changed the code as needed and uploaded it from an Arduino to the 825 and ran it on a breadboard using one light. It worked as expected by turning on and off 1 led. When I hooked up all 16 lights it would not work. I'm guessing it’s too much for the 825. When I ran the same sketch on a Arduino it ran all 16 lights. The road block that I’m facing is, I can turn the lights on with the remote but not turn them off. The program looks for a button push signal and when it finds one it turns on the lights and gets stuck in a loop. How can I get the sketch to continue to run the loop but pass the focus back to the button push to turn the speed of rotation up/down or off with the leds? A coworker told me I need a DoEvents function but Arduino doesn't have that.
I tried adding a timer but I’m not sure how that works.
Any thoughts?
#define IRpin_PIN PIND
#define IRpin 2
#define MAXPULSE 65000
#define NUMPULSES 50
#define RESOLUTION 20
#define FUZZINESS 20
uint16_t pulses[NUMPULSES][2];
uint8_t currentpulse = 0;
#include "ircodes.h"
int Speed = 1;
int DelayP = 40*Speed;
int DelayS = 10*Speed;
int On;
void setup(void) {
// Timer1.initialize(500000);
// Timer1.attachInterrupt(callback);
for (int thisPin = 4; thisPin < 8; thisPin++) {
pinMode(thisPin, OUTPUT);
}
}
void loop(void) {
int numberpulses;
numberpulses = listenForIR();
if (IRcompare(numberpulses, Play,sizeof(Play)/4)) {
On = 1;
if (On == 1) {
do{
for (int thisPin = 4; thisPin < 8; thisPin++) {
// turn the pin on:
digitalWrite(thisPin, HIGH);
delay(DelayP);
// turn the pin off:
digitalWrite(thisPin, LOW);
}
}
while(On ==1);
}
}
if (IRcompare(numberpulses, Speedup,sizeof(Speedup)/4)) {
Speed /= .5;
}
if (IRcompare(numberpulses, Slowdown,sizeof(Slowdown)/4)) {
++Speed;
}
if (IRcompare(numberpulses, Stop,sizeof(Stop)/4)) {
On = 0;
}
delay(500);
}
//KGO: added size of compare sample. Only compare the minimum of the two
boolean IRcompare(int numpulses, int Signal[], int refsize) {
int count = min(numpulses,refsize);
for (int i=0; i< count-1; i++) {
int oncode = pulses[i][1] * RESOLUTION / 10;
int offcode = pulses[i+1][0] * RESOLUTION / 10;
if ( abs(offcode - Signal[i*2 + 1]) <= (Signal[i*2 + 1] * FUZZINESS / 100)) {
}
else {
return false;
}
}
// Everything matched!
return true;
}
int listenForIR(void) {
currentpulse = 0;
while (1) {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
// KGO: Added check for end of receive buffer
if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
// KGO: Added check for end of receive buffer
if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
}
//void callback()
//{
// digitalWrite(10, digitalRead(10) ^ 1);
//}
[code]
Here is the timer code:
[code]
/*
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
* Original code by Jesse Tane for http://labs.ideo.com August 2008
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
* Modified June 2011 by Lex Talionis to add a function to read the timer
* Modified Oct 2011 by Andrew Richards to avoid certain problems:
* - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated
* - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing
* - Remove global enable of interrupts (sei())- could be running within an interrupt routine)
* - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt
* flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate
* at very short durations
* - startBottom() added to start counter at 0 and handle all interrupt enabling.
* - start() amended to enable interrupts
* - restart() amended to point at startBottom()
* Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis
* - renamed start() to resume() to reflect it's actual role
* - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* See Google Code project http://code.google.com/p/arduino-timerone/ for latest
*/
#ifndef TIMERONE_h
#define TIMERONE_h
#include <avr/io.h>
#include <avr/interrupt.h>
#define RESOLUTION 65536 // Timer1 is 16 bit
class TimerOne
{
public:
// properties
unsigned int pwmPeriod;
unsigned char clockSelectBits;
char oldSREG; // To hold Status Register while ints disabled
// methods
void initialize(long microseconds=1000000);
void start();
void stop();
void restart();
void resume();
unsigned long read();
void pwm(char pin, int duty, long microseconds=-1);
void disablePwm(char pin);
void attachInterrupt(void (*isr)(), long microseconds=-1);
void detachInterrupt();
void setPeriod(long microseconds);
void setPwmDuty(char pin, int duty);
void (*isrCallback)();
};
extern TimerOne Timer1;
#endif
[/code][/code]