<div dir="ltr">Paul,<div> You most likely know this, but in case it is not high on your mind right now, two points about millis() and micros() functions of the Arduino environment / Atmega chips when using interrupts:</div><div><br></div><div>1. If you use millis() in an ISR, It will not increment while in the ISR. So don't make multiple calls to millis(). The value will not change from the first call (i.e., the value when entered the ISR).</div><div><br></div><div>2. If you use micros() in an ISR and attempt to do delta timing, You have a chance of missing the TIMER0_OVF_vect and getting flaky results. Since you are using the micros() value that was the value when you entered the ISR, if the ISR goes on for too long you miss the overflow interrupt of timer0.</div><div><br></div><div>The above are because the functions involve interrupts in their code, and you are basically calling an interrupt inside an interrupt. Atmega boards like the Uno and the Mega generally do not use nested interrupts. I hope this makes sense.</div><div><br></div><div>Regards,</div><div>Doug P.</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022 at 11:40 AM Paul Bouchier <<a href="mailto:paul.bouchier@gmail.com">paul.bouchier@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Doug - Thanks for the suggestion about micros() instead of millis(). The minimum edge-to-edge period is 12ms, and at 1/4 speed is 48ms. So millis() would give better than 10% accuracy at full speed, and I wouldn't have to deal with micros() rolling over every 70 minutes. That said, maybe I should go for maximum accuracy. Do you think I need it?</div><div><br></div><div>Paul</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022 at 9:36 AM Doug Paradis <<a href="mailto:paradug@gmail.com" target="_blank">paradug@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">* micros()</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022 at 9:34 AM Doug Paradis <<a href="mailto:paradug@gmail.com" target="_blank">paradug@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Paul,<div> I would use micro() instead of millis().</div><div>Regards,</div><div>Doug P.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022 at 9:33 AM Paul Bouchier <<a href="mailto:paul.bouchier@gmail.com" target="_blank">paul.bouchier@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">Thanks Doug. What you describe is what I meant when I wrote <span style="font-size:12.8px">I'm thinking about adopting Pat's approach (which he gave up on) of measuring the period between count incrementing. </span>The encoder ISR would run each encoder transition and put the current value of millis() into a queue for consumption by an odometer task. This would allow the task to compute the most recent speed and delta-distance. I didn't express it very well :-(</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022, 9:22 AM Doug Paradis <<a href="mailto:paradug@gmail.com" target="_blank">paradug@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Paul,<div> Regarding the method of reading encoders. I suggest that you try pulse timing instead of pulse counting for low encoder ticks per period. The following is a quote from the article at <a href="https://www.motioncontroltips.com/how-are-encoders-used-for-speed-measurement/" rel="noreferrer" target="_blank">https://www.motioncontroltips.com/how-are-encoders-used-for-speed-measurement/</a>, "<span style="color:rgb(102,102,102);font-family:Raleway,sans-serif">With the pulse timing method, a high-frequency clock signal </span><span style="font-family:Raleway,sans-serif"><font color="#000000">(like the system clock)</font></span><span style="color:rgb(102,102,102);font-family:Raleway,sans-serif"> is counted during one encoder period (the pitch, or interval between two adjacent lines or windows). The number of cycles of the clock signal (m), divided by the clock frequency (f), gives the time for the encoder period (the time for the encoder to rotate through one pitch)."</span></div><div><font color="#000000"><br></font></div><div><font face="Raleway, sans-serif" color="#000000"> I suspect that if you look into the details of David 's code, he is actually using a P controller to correct the heading error with a Kp of 1 (or a scaled value) but doesn't call it a P controller. In other words, the "rotation" is something like rotation = delta encoder counts (i.e., rotation = Kp (delta encoder counts, where Kp = 1).</font></div><div><font face="Raleway, sans-serif" color="#000000"><br></font></div><div><font face="Raleway, sans-serif" color="#000000">Regards,</font></div><div><font face="Raleway, sans-serif" color="#000000">Doug P. </font></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 15, 2022 at 5:32 AM Paul Bouchier via DPRGlist <<a href="mailto:dprglist@lists.dprg.org" rel="noreferrer" target="_blank">dprglist@lists.dprg.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>David - going back to your description of how you manually turned the wheel a little bit when the speed was supposed to be zero, and the integral of speed error built up until it overpowered you and drove the wheel back to where it started - I'm confused because I don't understand how you must be calculating speed for that to be true. A naive implementation of speed-measurement would be to count the number of encoder counts in each 40ms tick. So when you manually moved the wheel, let's imagine there were a few ticks when a few counts were detected, then no more counts in any subsequent ticks. Speed should be zero after motion stops, so where's the error to integrate and cause corrective force to build up over time? Put another way, there was a speed error a few seconds ago but now there's no speed error; when does that error "go away", and when does the PID loop stop remembering it and trying to fight against it?</div><div><br></div><div>This is relevant to my current concerns with Mowbot, since it was discovered at Tuesday's meeting that the low rate of encoder ticks on Mowbot means I'll only see 2 or 3 counts per tick (hard to control), so I'm thinking about adopting Pat's approach (which he gave up on) of measuring the period between count incrementing. Pat - I'm also wondering why you gave up on that approach and changed encoders to one that has more counts - was there some basic flaw in the approach?<br></div><div><br></div><div>Thanks</div><div><br></div><div>Paul<br></div></div>
_______________________________________________<br>
DPRGlist mailing list<br>
<a href="mailto:DPRGlist@lists.dprg.org" rel="noreferrer" target="_blank">DPRGlist@lists.dprg.org</a><br>
<a href="http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org" rel="noreferrer noreferrer" target="_blank">http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>