I have a motor that spins. I have sensor on it so at each rotation I get short HIGH pulse from it to arduino pin 2.
So far in code I successfully attached an interupt to pin 2. But I want to calculate accurate motor speed by reading timer1 and reseting timer1.
Question: How can i read from timer1 and reset it immediatly to 0?
The next thing I would like to do is when the motor gets lets say at 30 degree angle, I need square output signal that will go high, stay high for 24 – 1500 us and go back to LOW. The motors speed is controlled by PID so in normal operation the speed of it is conastant and the idea is to set the desired delay between receiving the motor pulse and between turning the output signal HIGH in microseconds by the user. Also user should be able to set how long the HIGH should last (also in us). The best would be if i could take user's input, put it in correct registers, and this would run hardwired.
Question: Can I (and how) use the timer1 and somehow put something in registers and get hardwired comparison »if (timer1==value_in_register)« and when that is equal get the output of some pin (preferlly pin 14 on uno (PC0 (ADC0/PCINT8))) to change to HIGH, and stay there for some other value_in_registers and drop back to LOW again.
I am adding the following template as my code. If anyone is willing to help me out it would be most welcome.
///hardwire wired timer compare output to digital pin 14
//variables for time record on interrupt
volatile uint8_t state_update = 0;
volatile uint32_t timestamp0 = 0;
volatile uint32_t timestamp1 = 0;
uint32_t t_delay_until = 1000 ; //test value to put it registers as delay until output goes high
uint32_t t_delay_high = 1000 ; //test value to put it registers as delay how long to keep output high
void setup() {
//Interupt setup
pinMode(InterruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(InterruptPin), line_passed, FALLING );
}
void loop() {
if (state_update){
state_update = 0;
}
}
void line_passed() {
timestamp1=timestamp0;
///timer1 copy into timestamp0 ?
///timer1 reset ?
state_update = 1;
}
Please help me with those pieces of code regarding registers. Anything would help. I would kindly ask to extensively comment every line that has anything to do with registers since i am very weak in dealing with them. Like why is "this" line there? Where did you figure out to put it there? Where can i look at to read about that register that you set in "this" line? Everything else that could prove to be useful.
Why? This is a completely unconventional way to do it. If you are out of your depth, why not let the existing micros() function do the work for you (just one of many other ways)?
Example code won't do you any good until you understand what the hardware does. Chapter 16 of the datasheet. You'll probably want to use the Input Capture capability.
You don't need to reset the timer / counter. Just use unsigned subtraction of the previous value. Rollover will be handled correctly.
1. Configure TC1 so that it generates Time Tick for you at every minute. 2. You start TC1 and enable INT0 interrupt at the same time. 3. Let the ISRINTZ() populate the speedPulseCounter. 4. When you receive message (at the end of 1 minute time) from TC1, you disable interrupt, read the content of speedPulseCounter, convert it into speed/min, and show it on the Serial Monitor.
Because this way I will have highest precision which is the key in the project.
Where did you pull out the exact 1 minute time? why exactly 1 minute? And what will that tick do?
Okay start TC1 seems pretty clear, altho i am not sure how to actually execute the command. Can you please provide the line of code that would do it?
What will the INT0 do? Why enabling it?
What is ISRINTZ? is speedPulseCounter just a made up variable?
Is your process for averaging the speed in last minute? I want to calculate the speed only from last two pulses, so i can have the most accurate current speed. The motor spins at around 200 Hz (rounds per second), sometimes up to 240 Hz. Because it is changing a little, I would need the speed to be updated from last two rounds.
Can we look into this possibility? How can I do this?
OP wisely doesn't want to count pulses. The latency is huge with that, if you expect any reasonable accuracy. It's better to time pulses and calculate rotation by 1/t.
Counting pulses makes sense when the frequency is extremely high. In this case it's moderate. The ICP is a perfect choice, just a little tricky to use and only supported on one pin. It provides the absolute maximum possible resolution.
Thank you for all the input, especially for some examples for work with registers. I need around a day to study all the posts and try them out, and try to reconfigure the updating on every (pulse) round of a motor, so 200 updates per second. This will give the most recent speed - current speed, which is because of the inertia of the motor almost exactly the same until next round when next update happens.
I will come in a day or so, either for some more help if some huge unsolvable troubles appears or with the confirmation of successful solution. Thank you all for now.
Well, if you need that fast an update, okay. Normally, when the updates are that fast and the output is just for human readable purposes (actually I think you didn't say what is done with the data), it makes sense to low pass filter or average several readings to improve the accuracy.