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!
@@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 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? :)
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
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 ???
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
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?
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.
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
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?
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.
@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
@@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
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
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
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.
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.
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
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
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 ..
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.
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 ????
@@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 ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-uHoFfpLSb2g.html). I need to see some PID control with encoders, arduino was easy to find code, for the stm32f4, not so much.
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.
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
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