Hi guys this is my first post, for my project im trying to obtain an rpm value from two motors. i want to have the rpm show on my LCD screen, and obtain the data through a serial output. My code works after about 3 minutes of running the program im not quite sure how to set up the interrupts properly.
(i only included the main body tab)
LCD looks like:
To set interrupt, you need (pin, interruptroutine, type of change ) , You did fine except you need two interrupt routine, because you have 2 motors. And sensorState and sensorState2 should be declare volatile. Go visite http://arduino.cc/en/Reference/AttachInterrupt, I hope it will help.
example:
volatile long sensorState=0;
volatile long sensorState2=0;
void setup() {
attachInterrupt(0, encodermotorone, RISING); // 0 is digital pin 2 RISING mean when from 0 to 1
attachInterrupt(1, encodermotortwo, RISING); // 1 is digital pin 3
void encodermotorone()
{
// motor 1 routine here
}
void encodermotortwo()
{
// motor 2 routine here
}
To set interrupt, you need (pin, interruptroutine, type of change ) , You did fine except you need two interrupt routine, because you have 2 motors. And sensorState and sensorState2 should be declare volatile. Go visite attachInterrupt() - Arduino Reference, I hope it will help.
example:
volatile long sensorState=0;
volatile long sensorState2=0;
void setup() {
attachInterrupt(0, encodermotorone, RISING); // 0 is digital pin 2 RISING mean when from 0 to 1
attachInterrupt(1, encodermotortwo, RISING); // 1 is digital pin 3
void encodermotorone()
{
// motor 1 routine here
}
void encodermotortwo()
{
// motor 2 routine here
}
Thanks Techone i changed them to volatile and made two sub routines the funny thing is that the code works if i pull the supply to the motors out then it starts uploading to serial and writing to the LCD its almost as if the only thing running is the interrupt command and it doesn't have tome to run anything else. in saying that the motors are running at approximately 160 rpm 19 through the reduction gearbox which is 3040 rpm on the input where the encoder is positioned. This makes rpm16(incriments)=48640 points in a minute........
maybe i can't get an accurate result because there is just too much data do deal with in too little time?
Why do pulseIn inside an interrupt routine? That waits until the pin is high, it seems strange to do it there. Especially since you are using the same ISR (interrupt service routine) for both encoders, if one goes high you then sit there waiting for the other one to become high.
I have changed it to two different subroutines. The reason why i have used pulse in is so i get an instantaneous rpm rather than accumulating a massive variable. I'm not sure how else to achieve an rpm, i have been working on this for ages? Thanks for the input
Nick Gammon is right. I know you trying to calculate the RPM via pulseIn() - time between pulses. You can not get RPM at the same time, even with two interrupts. Because interrupt 0 is doing first and interrupt 1 is doing second. I got the feeling it not going to work well. But the solution I am thinking is to use a separed controller for each motors and a third one to collect data.
Well ( I trying to explain ) 1 CPU - data collecter - connect to two RPM counter - CPU controll . In that way you be possible to get RMP data and display it. OK Just like a human body work ( in a way ) The brain ( main CPU ) getting info and send info to a arm, legs, face, eyes, ear. Each of this parts "have" their own "CPU"... you get my idea ...
bobbcab:
The reason why i have used pulse in is so i get an instantaneous rpm rather than accumulating a massive variable.
There is no such thing as an "instantaneous rpm". An RPM, by definition, is done by counting the number of revolutions, per minute. You can't do it instantaneously. You could of course count the number per second, and multiply by 60, to get roughly the same effect.
Basically then your ISR needs to count revolutions, eg.
Then in your main loop you use millis () to keep track of elapsed time. When roughly a second has passed you fetch the number of revolutions, multiply by 60, and there you go! Your RPM calculated. Then set the number of revolutions back to zero for next time. You need a bit of tweaking to adjust for the actual time elapsed (ie. not "approximately a minute" but "exactly x milliseconds") and use that as part of your calculation.
Hey guys thanks for your reply. Sorry i took so long to get back to you. Thanks for your input but counting the revolutions is too hard a task as the variable runs out really quickly and this will create an average and when i slow the motors down it wont update. Technically you can obtain an instantaneous rpm eg when you look at your fan speed on your computer it is an instantaneous rpm. I hooked the encoder signal up to a CRO and found that it was a little gittery which produced a large error if i measure it over a longer period of time i should get the result i want (theoretically). Thanks for all the help guys.