I am working on a project using a Rotary Encoder and I am trying to receive the output from the encoder. As it stands I am able to get a count for degrees of change and direction of rotation, however depending on the speed the encoder spins I get a varying rotational output. For example if I rotate it slowly I can get 100's of counts for 180 degrees of rotation, but if I do so fast, then I could get 10 or so counts.
I believe my Arduino is running too slow to count each of the signals from the encoder, I measured the wavelength of a signal to be ~25 us when spun quickly but using the following code I found that my arduino is running at a loop rate of 200 loops per second.
void loop() {
if(counter <= 1000){
counter++;
Serial.println(counter);
}
}
The code for the Rotary Encoder: Dt and CLK pin representing the 2 signal wires, both being pulled up
void loop(){
//take clk pin state
clkState = digitalRead(clkPin);
//if clk state changed then wheel is rotating, react to rising edge to avoid double count
if(clkState != preClkState && clkState == HIGH){
Serial.write(digitalRead(dtPin));
//check direction of spin based on dtpin
if(digitalRead(dtPin)== HIGH){
counter++;
clockwiseDirection = true;
}else{
counter--;
clockwiseDirection = false;
}
//output values
Serial.write("Direction: ");
if(clockwiseDirection){
Serial.write("Clockwise | Counter: ");
}else{
Serial.write("Counter Clockwise | Counter: ");
}
Serial.print((int)counter);
Serial.print("\n");
}
//update pre pos
preClkState = clkState;
}
-
1Is it possible that all of the data printed to the Serial Monitor maybe slowing things down a bit?VE7JRO– VE7JRO2023年10月13日 02:34:57 +00:00Commented Oct 13, 2023 at 2:34
-
1you should use interrupts instead of digitalRead to ensure responsive scrolling. and yeah, don't print each detent.dandavis– dandavis2023年10月13日 06:09:54 +00:00Commented Oct 13, 2023 at 6:09
1 Answer 1
Serial transmission takes time. Let's assume that you have set up the Serial
with 9600 baud. This means 9600 bits per second. A single byte transmission commonly consists of a start bit, the data bits, and a single stop bit. This gives a total of 10 bits per byte. Therefore, your transfer rate is 9600 bits/s / 10 bits/byte = 960 bytes/s.
Estimating with a quick look at your source, each loop of your sketch sends about 40 characters, commonly encoded as a byte per character. And you claim that it achieves 200 loops per second, so the transfer rate is 40 bytes/loop * 200 loops/s = 8000 bytes/s.
Calculating back to bits/s results in a baudrate of roughly 80000 bits/s. So presumably you set up your Serial
with 57600 or 115200 baud.
How to solve the issue?
Separate the acquisition of the encoder data from the transmission of the counter value. You can use interrupts, for example on the clock signal. However, this is not for the faint heart.
The Serial
uses a transmission buffer of unspecified size. See the last paragraph of its documentation:
As of Arduino IDE 1.0, serial transmission is asynchronous. If there is enough empty space in the transmit buffer,
Serial.write()
will return before any characters are transmitted over serial. If the transmit buffer is full thenSerial.write()
will block until there is enough space in the buffer. To avoid blocking calls toSerial.write()
, you can first check the amount of free space in the transmit buffer usingavailableForWrite()
.
You can check that the transmit buffer has room for your message. Send only, if there is enough room.