So I am very new to Arduino, and in fact all programming languages, but having to learn fast as it will play a main part in Masters final year project in Mechanical Engineering!
That aside, I was quickly made aware that I was going to have to do some 'bit-banging', which is where I start to get confused!
My first task was to try and get an LED to flash at 1Hz using Atmega 328's timer 1. This is my code, it works however doesn't blink at 1Hz. More like 0.23Hz i.e LED on for ~4s? Can anybody offer advice as to why this might be the case?
#include <avr/io.h> #include <avr/interrupt.h>
int ledPin = 13;
int state = 0;
void setup() {
pinMode(ledPin, OUTPUT);
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
//Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1
OCR1A = 15624; // Set CTC compare value to 1Hz at 16MHz AVR clock, with a prescaler of 1024
TCCR1B |= ((1 << CS10) | (1 << CS12)); // Start timer at Fcpu/1024
TCCR1B &= ~((1 << CS11));
TCCR1B &= ~((1<<WGM13)); //clears all bits
//TCCR1A &= ~((1<<WGM11) | (1<<WGM10)); //clears all bits
TCCR1A = 0x00; // Adifferent way of clearing all bits?
TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
sei(); // Enable global interrupts }
}
void loop() { // Can loop forever, because the ISR will deal with everything
}
//
ISR(TIMER1_COMPA_vect) {
state = 1 - state;
digitalWrite(ledPin, state);
TCNT1 = 0x00;
}
Well what I really want to do is PWM an AC water pump. Not how you may think though as I know this is not possible so what I thought is I could generate a saw-tooth wave such that Arduino counts up to its operating voltage and then back down in a REGULAR time period, of say 10 seconds, 0.1Hz. The key is this time period needs to be regular and measurable. Once I have this, I would like to compare an analogue signal coming in, say from a POT, compare it to the saw-tooth value at that instant in time and for every time the analogue signal is greater than the value of the saw-tooth digitally turn the pump ON. When below, OFF. If you can see what I am saying and my logic is correct then what you would get is the pump turning on/off for varying amounts of time dependant on the input. If you have any suggestions on another way of me achieving this that would be greatly appreciated.
so what I thought is I could generate a saw-tooth wave such that Arduino counts up to its operating voltage and then back down in a REGULAR time period, of say 10 seconds, 0.1Hz.
"Counts up to it's operating voltage" needs further explanation. What are you planning to count?
Well I guess up to 1023? 1 less than the maximum value read by Arduino for any analogue input signal. So for example if I turn my POT to max, Arduino reads 1024 and thus the pump will remain on the whole time. Hope that makes sense.
Ok, well don't worry about that just for now thanks.
Is the Arduino using the 16MHz crystal by default? If its not how do I select it? If it is can you see why my code isn't toggling the sate of my LED at 1Hz?
Greetings, the good news is that you are making this task much more complicated than it needs to be. In CTC mode is that you can set up the Arduino to toggle a pin on a compare-match in hardware. You can use an interrupt routine but it isn't even necessary. This tutorial is helpful if you are just learning about timers (and also check out the datasheet for the atmega168/328) http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=50106&start=0
Note that this only works on the PB1 (or arduino 9).. so if you want to toggle the arduino LED pin you need to use your match interrupt routine to change it.
Jarv. Thank you, this is interesting. I have been through the datasheet a good few times but as I'm sure your aware its not the most forgiving for beginners! Anyway I managed to get my code (with interrupts) to work such that it toggles the LED state at 1Hz, here it is for the record:
#include <avr/io.h> #include <avr/interrupt.h>
#define ISR_TIMER1_COUNT 15625 // 16.0MHz clock / (prescaler = 1024) #define ledpin 13
int state = 0;
void setupTimer1(void)
{
While things are fresh in your mind you should go back and add some meaningful comments that will be of genuine use when you try to reimplement these techniques in the future. Specifically you want to indicate why you are setting/clearing the particular bits. Take a look at the program code I posted here (Generate high frequency square wave - #6 by floresta - Project Guidance - Arduino Forum) for some ideas. I believe that this code is using the technique that jarv is using but it is using Timer/Counter2. There's a lot more comment than code there but the extra time it took me to generate the comments will be paid back in the future, take my word for it.
You might also want to follow the Reference Diagrams For Programmers link in the Atmel ATmega Subsystem Diagrams section at http://web.alfredstate.edu/weimandn/ and look at the various Timer/Counter diagrams.
To post program code you should highlight the part of your post that is code and click on the '#' button. It is a lot easier to follow when you do this.