Well, I have exactly the same rotary encoder. Except, mine has second designaton "400BM" not "600 BM". Cool stuff man! I am glad you explained how it can be interfaced so that I can use it without fiddling too much. Thumbs up!
FWIW, the instructions for connecting the rotary encoder need some update. You are pulling up the outputs of the encoder to 5V. This only works if the ports you are using are 5V tolerant. Some pins of the MCU are not 5 volt tolerant. You can get rid of the external pull-up with resistors and use the pull-ups on the microcontroller. Outputs of these encoders are open drain so they will also work with 3.3 Volts so you can connect them to all the pins without worrying about 5V tolerance.
I agree on keeping an eye on pin voltage tolerances , that said this is an open collector NPN based encoder not a FET type with a min input of 5v , i tried it with 3.3 , also all except 2 pins on port B are 5v tolerant which i think is why the onboard decoder supports only port B, while all but 5 pins on port A are 3.3 ,. nonetheless I should have explained that. Next time. lol
@@EdwinFairchild yep if you have one of the stm32f4 discovery boards (stm32f4 11ve i thinki) i think those come with an onboard gyro and other peripherals which talk to via SPI haha. Somehow this stuff always makes more sense when you explain it. Keep up the good work . Thanks
Great video. Since encoders are just rotating switches, if you want repeatable results (especially with lower quality encoders), you may need to debounce the inputs from the encoder (just like you would with a switch). There is a digital input filter in the timers (including encoder mode), but it looks like that only helps if your pulses are in the microsecond (to maybe tens of microseconds) range; I don't think it can slow its sampling rate down enough for pulses in the millisecond range.
the STM32 micro already have a filter parameter in the hardware to prevent the bouncing encoder inputs. I normally set this filter to 10 in decimal and it works perfect
That is a useful feature, thanks for pointing it out. So the hardware version uses unsigned 16 bit integers which means I have to keep a sign bit for when it underflows. Is it possible to assign the timer to a signed integer? Is there a timer interrupt for underflow? Another thought is that if you set the upper limit to the number of pulses per complete turn then you can use the timer overflow interrupt for a turn (revolution) counter. I’m also assuming one encoder per timer is possible.
You should always watch for underflow/overflow if you using counters. If it is unsigned, for example unsigned short x = 65535, then you can use casting operator, something like: (signed short) x ; to change from unsigned to signed. Just pay attention to "two's complement", and in the case of unsigned short x = 65535, when you change to short x, then you will get -1.
yup all you said Klave is true. There are interrupts for just about everything in the timers. And yes one timer per encoder because there is only one Count register per timer.
Yes you can just type cast the register value to a signed 16bit " (int16_t)TIM4->CNT " and then print that out to get signed numbers> i think ill put that in the description just for clarity's sake.
okay, without trying to understand this (yet), can I offload this to hardware in case of I2C encoders? Multiple I2C encoders connected through I2C multiplexer? Probably not, right?
Well i2c is hardware , but since it requires you sending commands of sorts then in that case no, the hardware has no way of know what you want the commands to be. Unless these devices are just sending data without you needing to ask for it,then you can use DMA and not have to worry about it
Hi Eddie, if you use encode using hardware, how the program Know that encoder was moved? if you are not checking the CNT all the time (using poll mode).....can we use an interruption to know know the CNT was changed? thanks in advance, your videos are the best. Saludos desde Argentina Alfredo
Well this method is more like any time you read the variable you know you have the current position of the encoder , if you want to know Everytime it moved then yes you can set an interrupt . But with this method the variables will always have the latest value of the enconder. So it's up to you to decide which behaviour you like best for your application
Great videos! I like when you learn out how to code the hard way with 0101010101 + data sheets. By the way. Can you show CAN bus and USB serial communication? :)
very good job dude and rich content ... i was trying to make a tester for encoders with stm32 thanks a lot . which software did you use for serial debug ???
Eddie, This was a good video. I'm trying to do the same thing using a blue pill and the Arduino IDE with Roger Melbournes library. I have set the registers according to the datasheet, and I have set the SMS bits in the SMCR register to 011 (Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input.) but my counter does not count on every edge of TI1 and TI2. Instead, when rotating clockwise, it counts up on the rising and falling edges of TI1 (but not TI2). When rotating counterclockwise, it counts down on the rising and falling edges of TI2 (but not TI1). This messes up my counter when I have jitter, because it doesn't count up AND down during jitter. Any ideas? According to the Figure 134 in the reference manual, it should count up and down on the rising AND failling of TI1 and TI2 always. Help?
Oh, it is quite annoying to see that my helping message ends in "likely spam". Eddie, you can include me in "moderator" list( in beta studio); Video Manager->Settings->Community->Moderators (or Approved users), so that next time I post here comment including link, it will not end in "likely spam". Thank you in advance.
great video. Do you know if this will work for a motor to count the encoder (quadrture) pulses i.e. I have a moto geared encoder that has about 11 magnetic segments and produces hundreds of pulses persecond. I need to calc the RPM and communicate this to an RPi - ideas?
Awesome, thanks for sharing! I am using the STM32F407VET6, could this do 3 or 4 motor encoders at the same time (enough timers and what timers # would you use?)? TIA
@Eddie Amaya Hello Eddie first of all thank you for posting the video. Secondly, i have a question concerning the val because you initialized as an uint32_t wich means no negatives values then how it can be negatives in the timer interruption because maybe the code was not too clear to me. Thank you in advance.
It is never negative ! If you look at the end of the video if goes up to 65535 and then back to zero, if you go the other way once it goes past zero it will go to 65535. Val-- means val - 1 , it just subtracts 1 from the current val, when it goes past 0 it's underflows back to 65535
Great Explanation. I need to calculate the frequency of the motor. Is there any provision to stop decrementing? Since the direction bit will be set by hardware, I need only incrementing the counter when rotor turns in any direction. counter value I will copy periodically and will clear the counter register. Based on the counter value and my predefined period I can calculate the frequency of the rotor. Please suggest me if there is any scope for improving my procedure to calculate frequency of rotor
You could just use the absolute value of the change in the timer's counter value. If you want the counter to increment for any change (in either direction, including back-and-forth), then you probably want to configure the timer in one of the external clock modes (probably external clock source mode 2), and connect one of the encoder's outputs to that external clock input. Leave the other encoder output disconnected. You will get less resolution than you could get in encoder mode (because you are ignoring edges on the other encoder output). You can use the timer's prescaler to divide the external pulses; if you set it to the number of pulses per revolution, the timer's counter will have the number of complete revolutions.
Great tutorial. Thanks!!!. Quick question: Is there a way to overcome the 65535 limit on the encoder count?. I am working with a linear scale encoder which sends much more pulses than 65535. Thanks again.
Yeah just keep track of how many times you have overflowed your varaible or use a different variable type instead of using the count as a value use it as a tick and increment a 32 bit varaible or something . I mean there's tons of ways
Just finished building one with an lcd(those 16x2s) with the f103c8t6 with those cheap encoders .... I'm using 1 input only ... works great .... these ones give 40 counts for full 360 rotation .. if both inputs used ,, it will give 80 ... not that great but still good ... your encoder is tooooooo expensive for me ..... haha ..
Hello,I’m a learner for stm32. Thanks for your tutorial videos. I learned much here. Could you make a video for nvic scs scb registers? I used keil before. Now,I try to build it on linux with libopencm3. They have much different between functions. When I use interrupts more than 2. I don’t know how to set the preemption priority and subprority by registers. Sorry about my request. I am really confused by nvic scs scb registers.
@@clawsoon I don't recall if I was pulling up to 5v , in that case the internal pullups only pull to 3.3v but then again I was reading on the pins so maybe it was not 5v lol. As far as what is "better" depends on project specifics. For example if you're working on a project where 5 million units will be made you can save a few cents and use the internal pullups to keep part count down . At least that is my theory from my inexperienced mind lol . Still in school so take my advice with a grain of salt
@@Ozzy3333333 there are a lot of resources to learn PID control. Start there. Learn what they are , the math and theory behind it. ARM has a library for PID control umm I did some playing with that before and I have to dig out the project files. Right now it's though because I just moved and all my things are in boxes
@@EdwinFairchild thanks for the reply. I know what PID is and how to dial it in (been doing industrial control tuning for a while and in the last 6 years quad tuning / flying (see my flying here czcams.com/video/uHoFfpLSb2g/video.html). I need to see some PID control with encoders, arduino was easy to find code, for the stm32f4, not so much.
Great video. Do you know how to use DMA to put the counter value into a variable? I know that the DMA could grab for example TIM1_CH1, TIM_CH2, etc, but in the manual, it doesn't say that it can get the counter value (which is computed by the hardware)? Thanks again.
If you know the address of the counter register then perhaps try to do a DMA transfer from memory to memory , or peripheral to memory but in peripheral to memory I think the peripheral needs to trigger a DMA request. I'm not sure so give it a shot
Hello , i have implemented the same interrupt version but i am not getting encoder counts on serial monitor it remains 0.....you have any clue to this what can be wrong ????
Hey Eddie, thanks for the vids teaching about stm32, they are awesome!! I need to set PWM on the PA9 and PA10, I can not make it work on my bluepill idk why. Do you have a clue?
@@EdwinFairchildI do know how to set pwm output for other timers, but timer 1 is specially difficult to do, Idk why I can't set a pwm using channels from tim1.
That depends a lot on the hardware being used, are the pulses coming in nice clean pulses from something like a very high end encoder, what speed is your microcontroller running at and other factors I would assume. Off the top of my head I don't know. But I do know not that many encoders are going to output anything in the MHZ range that would be really fast to spin that thing and then you have to take into account physics ... Is it getting hot? Anyways it's an interesting question sorry I can't give you a definite answer. I'm not sure the datasheet mentions how fast I can count I'll have to check
@@EdwinFairchild Thanks Eddie.You are right about encoders not outputting pulses in the MHz range.I was curious about the speed because there does not seem to be a clock for the counter per se. Also is it possible to be able to get the speed of the pulses ( pulse width) while counting the pulses ? It would be useful to calculate the acceleration of the actuator etc.Thanks for your videos,its great that you code from datasheets and user manuals than just relying on tools like CubeMX.
@@EmbSysDev well the encoder pulses become the "clock" and that's what causes the counter to increment or decrement , furthermore you could add a timer and use that to measure pulse width
Hi, Could you give a link or make video how to program these bluepills STM32? I mean which software to install and step by step hello world example. Not Arduino EDI but something where you can program it directly like AtmelStudio or so. Thank you.
@@EdwinFairchild well I'm not familiar with all of it, so I was looking for installation and wiring up step by step. But I just did hello world, project. So sorry for dummy question.
check the day this video was made, CubeIDE did not exist. but I still do not use Cube IDE, I use mostly visual studio IDE community edition with VIsualGDB
You are making a small mistake.............you have pulled up STM32 pins to 5 volt.........not all STM32 pins are NOT 5 Volt Tolerant..........reduce the 5 Volt pulses to 3.3 V using a voltage divider , and then feed then into STM32 pins
Well, I have exactly the same rotary encoder. Except, mine has second designaton "400BM" not "600 BM". Cool stuff man! I am glad you explained how it can be interfaced so that I can use it without fiddling too much. Thumbs up!
FWIW, the instructions for connecting the rotary encoder need some update. You are pulling up the outputs of the encoder to 5V. This only works if the ports you are using are 5V tolerant. Some pins of the MCU are not 5 volt tolerant. You can get rid of the external pull-up with resistors and use the pull-ups on the microcontroller. Outputs of these encoders are open drain so they will also work with 3.3 Volts so you can connect them to all the pins without worrying about 5V tolerance.
I agree on keeping an eye on pin voltage tolerances , that said this is an open collector NPN based encoder not a FET type with a min input of 5v , i tried it with 3.3 , also all except 2 pins on port B are 5v tolerant which i think is why the onboard decoder supports only port B, while all but 5 pins on port A are 3.3 ,. nonetheless I should have explained that. Next time. lol
patiently waiting for your SPI video great stuff as always thanks
definitely, I need to get my hands on something tht uses SPI to work with. I will check amazon what I can get cheap and quick.
actually i can just make to microcontrollers talk to each other haha. Ill do that.
@@EdwinFairchild yep if you have one of the stm32f4 discovery boards (stm32f4 11ve i thinki) i think those come with an onboard gyro and other peripherals which talk to via SPI haha. Somehow this stuff always makes more sense when you explain it. Keep up the good work . Thanks
Great video. Since encoders are just rotating switches, if you want repeatable results (especially with lower quality encoders), you may need to debounce the inputs from the encoder (just like you would with a switch). There is a digital input filter in the timers (including encoder mode), but it looks like that only helps if your pulses are in the microsecond (to maybe tens of microseconds) range; I don't think it can slow its sampling rate down enough for pulses in the millisecond range.
the STM32 micro already have a filter parameter in the hardware to prevent the bouncing encoder inputs. I normally set this filter to 10 in decimal and it works perfect
That is a useful feature, thanks for pointing it out. So the hardware version uses unsigned 16 bit integers which means I have to keep a sign bit for when it underflows. Is it possible to assign the timer to a signed integer? Is there a timer interrupt for underflow?
Another thought is that if you set the upper limit to the number of pulses per complete turn then you can use the timer overflow interrupt for a turn (revolution) counter. I’m also assuming one encoder per timer is possible.
You should always watch for underflow/overflow if you using counters. If it is unsigned, for example unsigned short x = 65535, then you can use casting operator, something like: (signed short) x ; to change from unsigned to signed. Just pay attention to "two's complement", and in the case of unsigned short x = 65535, when you change to short x, then you will get -1.
yup all you said Klave is true. There are interrupts for just about everything in the timers. And yes one timer per encoder because there is only one Count register per timer.
Yes you can just type cast the register value to a signed 16bit " (int16_t)TIM4->CNT " and then print that out to get signed numbers> i think ill put that in the description just for clarity's sake.
Great stuff indeed !
Excellent video Eddie.
okay, without trying to understand this (yet), can I offload this to hardware in case of I2C encoders? Multiple I2C encoders connected through I2C multiplexer? Probably not, right?
Well i2c is hardware , but since it requires you sending commands of sorts then in that case no, the hardware has no way of know what you want the commands to be. Unless these devices are just sending data without you needing to ask for it,then you can use DMA and not have to worry about it
Sir, can you share the circuit diagram. I don'T know how can i connect the encoder to our STM32.
Hi Eddie,
if you use encode using hardware, how the program Know that encoder was moved? if you are not checking the CNT all the time (using poll mode).....can we use an interruption to know know the CNT was changed?
thanks in advance, your videos are the best.
Saludos desde Argentina
Alfredo
Well this method is more like any time you read the variable you know you have the current position of the encoder , if you want to know Everytime it moved then yes you can set an interrupt . But with this method the variables will always have the latest value of the enconder. So it's up to you to decide which behaviour you like best for your application
This was gold!
Great videos! I like when you learn out how to code the hard way with 0101010101 + data sheets. By the way. Can you show CAN bus and USB serial communication? :)
Tx. Didn't know about this, so now I do 🙂
Well there you have it 😁
Well done . Extremely detailed content .
Depends what ide you are using bit if it's eclipse based it's all in the eclipse marketplace
very good job dude and rich content ... i was trying to make a tester for encoders with stm32 thanks a lot . which software did you use for serial debug ???
Eddie, This was a good video. I'm trying to do the same thing using a blue pill and the Arduino IDE with Roger Melbournes library. I have set the registers according to the datasheet, and I have set the SMS bits in the SMCR register to 011 (Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input.) but my counter does not count on every edge of TI1 and TI2. Instead, when rotating clockwise, it counts up on the rising and falling edges of TI1 (but not TI2). When rotating counterclockwise, it counts down on the rising and falling edges of TI2 (but not TI1). This messes up my counter when I have jitter, because it doesn't count up AND down during jitter. Any ideas? According to the Figure 134 in the reference manual, it should count up and down on the rising AND failling of TI1 and TI2 always. Help?
Thanks for all your videos.
Oh, it is quite annoying to see that my helping message ends in "likely spam". Eddie, you can include me in "moderator" list( in beta studio); Video Manager->Settings->Community->Moderators (or Approved users), so that next time I post here comment including link, it will not end in "likely spam". Thank you in advance.
Great! Could you make tutorials on more advanced topics in maybe more advanced microcontrollers?
Not making any tutorial for the rest of this year probably. Life has a way to derail plans.
great video. Do you know if this will work for a motor to count the encoder (quadrture) pulses i.e. I have a moto geared encoder that has about 11 magnetic segments and produces hundreds of pulses persecond. I need to calc the RPM and communicate this to an RPi - ideas?
Awesome, thanks for sharing! I am using the STM32F407VET6, could this do 3 or 4 motor encoders at the same time (enough timers and what timers # would you use?)? TIA
@Eddie Amaya Hello Eddie first of all thank you for posting the video. Secondly, i have a question concerning the val because you initialized as an uint32_t wich means no negatives values then how it can be negatives in the timer interruption because maybe the code was not too clear to me. Thank you in advance.
It is never negative ! If you look at the end of the video if goes up to 65535 and then back to zero, if you go the other way once it goes past zero it will go to 65535. Val-- means val - 1 , it just subtracts 1 from the current val, when it goes past 0 it's underflows back to 65535
@@EdwinFairchild thank you very much for the explanation 😊
Great Explanation. I need to calculate the frequency of the motor. Is there any provision to stop decrementing? Since the direction bit will be set by hardware, I need only incrementing the counter when rotor turns in any direction. counter value I will copy periodically and will clear the counter register. Based on the counter value and my predefined period I can calculate the frequency of the rotor. Please suggest me if there is any scope for improving my procedure to calculate frequency of rotor
You could just use the absolute value of the change in the timer's counter value.
If you want the counter to increment for any change (in either direction, including back-and-forth), then you probably want to configure the timer in one of the external clock modes (probably external clock source mode 2), and connect one of the encoder's outputs to that external clock input. Leave the other encoder output disconnected. You will get less resolution than you could get in encoder mode (because you are ignoring edges on the other encoder output). You can use the timer's prescaler to divide the external pulses; if you set it to the number of pulses per revolution, the timer's counter will have the number of complete revolutions.
Great tutorial. Thanks!!!. Quick question: Is there a way to overcome the 65535 limit on the encoder count?. I am working with a linear scale encoder which sends much more pulses than 65535. Thanks again.
Yeah just keep track of how many times you have overflowed your varaible or use a different variable type instead of using the count as a value use it as a tick and increment a 32 bit varaible or something . I mean there's tons of ways
Hey Sohan, did you get anywhere on your project? I'm starting something similar and would hate do reinvent the wheel. Thanks
Just finished building one with an lcd(those 16x2s) with the f103c8t6 with those cheap encoders .... I'm using 1 input only ... works great .... these ones give 40 counts for full 360 rotation .. if both inputs used ,, it will give 80 ... not that great but still good ... your encoder is tooooooo expensive for me ..... haha ..
How may I set up this Black backgroud color?
Hello,I’m a learner for stm32.
Thanks for your tutorial videos.
I learned much here.
Could you make a video for nvic scs scb registers?
I used keil before.
Now,I try to build it on linux with libopencm3.
They have much different between functions.
When I use interrupts more than 2.
I don’t know how to set the preemption priority and subprority by registers.
Sorry about my request.
I am really confused by nvic scs scb registers.
Exactly what I was looking for, thanks. One question: Why do you have to use external pullup resistors instead of just setting the pin mode to pullup?
You don't HAVE to.
@@EdwinFairchild But you did. :-) Are external pullups better in this case?
@@clawsoon I don't recall if I was pulling up to 5v , in that case the internal pullups only pull to 3.3v but then again I was reading on the pins so maybe it was not 5v lol. As far as what is "better" depends on project specifics. For example if you're working on a project where 5 million units will be made you can save a few cents and use the internal pullups to keep part count down . At least that is my theory from my inexperienced mind lol . Still in school so take my advice with a grain of salt
@@EdwinFairchild Thanks for going into detail. I'm a complete amateur, so you're way ahead of me. :-)
Any help/suggestions for brush PID motor control with encoder? Where to start?
that sounds like a fun project actually
@@EdwinFairchild could you give me a push in the right direction to start or? TIA!
@@Ozzy3333333 there are a lot of resources to learn PID control. Start there. Learn what they are , the math and theory behind it. ARM has a library for PID control umm I did some playing with that before and I have to dig out the project files. Right now it's though because I just moved and all my things are in boxes
@@EdwinFairchild thanks for the reply. I know what PID is and how to dial it in (been doing industrial control tuning for a while and in the last 6 years quad tuning / flying (see my flying here czcams.com/video/uHoFfpLSb2g/video.html). I need to see some PID control with encoders, arduino was easy to find code, for the stm32f4, not so much.
Great video. Do you know how to use DMA to put the counter value into a variable? I know that the DMA could grab for example TIM1_CH1, TIM_CH2, etc, but in the manual, it doesn't say that it can get the counter value (which is computed by the hardware)? Thanks again.
If you know the address of the counter register then perhaps try to do a DMA transfer from memory to memory , or peripheral to memory but in peripheral to memory I think the peripheral needs to trigger a DMA request. I'm not sure so give it a shot
Wait a minute why can you just make a pointer to the counter ???
@@EdwinFairchild good idea, I'll do that. I got led into the DMA idea from the end of the video... thanks Eddie :)
Hello , i have implemented the same interrupt version but i am not getting encoder counts on serial monitor it remains 0.....you have any clue to this what can be wrong ????
Some error in your code or hardware
Hey Eddie, thanks for the vids teaching about stm32, they are awesome!! I need to set PWM on the PA9 and PA10, I can not make it work on my bluepill idk why. Do you have a clue?
Look at 11:49 and read the comments under hardware setup function
@@EdwinFairchildI do know how to set pwm output for other timers, but timer 1 is specially difficult to do, Idk why I can't set a pwm using channels from tim1.
Hi, how does one know the maximum frequency of the pulses which can be counted? i.e. before we start loosing pulses being counted.
That depends a lot on the hardware being used, are the pulses coming in nice clean pulses from something like a very high end encoder, what speed is your microcontroller running at and other factors I would assume. Off the top of my head I don't know. But I do know not that many encoders are going to output anything in the MHZ range that would be really fast to spin that thing and then you have to take into account physics ... Is it getting hot? Anyways it's an interesting question sorry I can't give you a definite answer. I'm not sure the datasheet mentions how fast I can count I'll have to check
@@EdwinFairchild Thanks Eddie.You are right about encoders not outputting pulses in the MHz range.I was curious about the speed because there does not seem to be a clock for the counter per se. Also is it possible to be able to get the speed of the pulses ( pulse width) while counting the pulses ? It would be useful to calculate the acceleration of the actuator etc.Thanks for your videos,its great that you code from datasheets and user manuals than just relying on tools like CubeMX.
@@EmbSysDev well the encoder pulses become the "clock" and that's what causes the counter to increment or decrement , furthermore you could add a timer and use that to measure pulse width
Hi,
Could you give a link or make video how to program these bluepills STM32? I mean which software to install and step by step hello world example. Not Arduino EDI but something where you can program it directly like AtmelStudio or so.
Thank you.
Are you joking? That's what all my videos are.
@@EdwinFairchild well I'm not familiar with all of it, so I was looking for installation and wiring up step by step. But I just did hello world, project. So sorry for dummy question.
@@goodwill7643 no worries just enjoy the channel and learn what you can from it. As I slowly release more content
Why don`t you uses the STM32CubeIDE? The TrueSTUDIO is better, if so, why? THX.
check the day this video was made, CubeIDE did not exist. but I still do not use Cube IDE, I use mostly visual studio IDE community edition with VIsualGDB
You are making a small mistake.............you have pulled up STM32 pins to 5 volt.........not all STM32 pins are NOT 5 Volt Tolerant..........reduce the 5 Volt pulses to 3.3 V using a voltage divider , and then feed then into STM32 pins
All of port B except 3 pins are 5v tolerant specially the pins for the encoder.
This was asked and explained on a previous comment. Maybe I'll put it in the description.
Quien es el que está abajo que no hace nada?
You can share code?
Check my blog