-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Motor Driver - Code Style and Timers #37
Comments
I'm not sure what you mean by 30hz or 50hz, but a reasonable reaction speed is very useful. The arduino can react much faster than the pi to certain faults (like reflex pulling away from being burned) I use the external jumpers. I have 4 different versions of actual hardware I have built so the software never needs to be modified and there is not a problem of flashing the wrong version and needing to tweak the config. Unfortunately there are only so many io available for these straps, so if you use a different module you might need to recompile. I am using custom timers, yes. This is needed. The arduino is clocked down to 4mhz, but the pwm frequency needed is 16khz. So to properly switch the mosfets and also control the deadtime it is needed to use interrupts actually making them naked to save cycles and give a better duty cycle. I agree that you could simplify the code perhaps somewhat but end up with an inferior driver on the same hardware. I am happy to accept a pull request that improves the code. |
Thank you very much for the quick response! Since your version is considered to be currently usable and stable, I will make a branch or fork and make changes there. The main difference is that your code is optimized to work with bare metal H-Bridges and my code does not need that functionality. That's why I want to separate the versions and create one that uses generally the same functions and interfaces (especially the uart communication) but rewrite everything that requires custom timers for the following reason: The already supported vnh2sp30 doesn't need it and my proposed IBT2 H-Bridge also doesn't need it. These can simply be operated using one or two PWM outputs (analogWrite()) and a bunch of IOs (digitalWrite()). Questions:
My understanding: void disengage() stops the rudder, turns the engage flag off and turns off the above LEDs void detach() turns off all PWM generators void update_command() takes the last value (lastpos) and drives it towards the commanded value (some value between 0 and 2000), applies a slew rate to it and sends it to position() Now the interesting part that I don't yet understand Regarding your questions: At the end of loop() you send the telemetry back to PyPilot at ... it seems ... as fast as you can. Is that correct? So it basically sends data all the time with no pause in between packages? How often does PyPilot send a new data package to motor.ino? |
The 50hz loop controls the slew rates so that they work correctly. The telemetry is sent as fast as commands are received, so pypilot controls the data rate. This gives a higher data rate when pypilot is run at 25hz instead of the default 10. pypilot usually sends 2-3 packets (4 bytes each) per iteration. rudder feedback is optional and pypilot works without. The motor controller does prevent further movement outside rudder limits which gives a slightly quicker reaction than using python for this. It basically works ok to use python for this control which is the case if the rudder feedback is supplied via nmea to pypilot rather than through the controller. The engage function does not jerk or reset speed because at first it does nothing if already engaged: if(flags & ENGAGED) { |
Thanks for the additional explanation! I'm digging through this right now. |
Could you please help me understand what you are doing with rudder_sense? I'm specifically interested in understanding the bottom portion of the code `const int rudder_react_count = 40; // approx 0.1 second reaction
|
I generally got the system working. It communicates and I see my rudder sensor when I move the rudder. It engages but I get a DRIVER_TIMEOUT displayed in Autopilot Control. When is this set and why? |
This is a rather confusing flag which indicates that no current (amps) is detected and therefore the motor is likely disconnected. This would obviously be the case if no hbridge is attached. maybe it should be renamed to NO_MOTOR ? |
@McNugget6750 writes:
Hi Timo. We should talk. I'm also doing this right now (I want to integrate IBT-2 support), and I'm concerned that we're going to end up doing duplicate work which can't be reconciled. I have mostly finished changes to make the choice of driver be a compile-time thing, in a way that we can add support for new drivers (you and I want IBT-2, and @partyvi is working on TI DRV8873H). I believe/hope we can get away with only having one current sense line (I talk about it here): http://forum.openmarine.net/showthread.php?tid=1840&pid=10976#pid10976 And I think the two enable lines can be joined and driven as one. @seandepagnier writes:
If we want to continue to be able to select this at run time, one way might be to use certain values of resistor on an analog pin. Anyway, here is my unfinished work in progress. I don't have hardware to test it on yet, but I'm running it through the preprocessor for each driver, and comparing the output to the original.
|
@CapnKernel Hey Mitch, I'm too far along now. I completely agree that double work is not a good idea and the code base should always be maintained by one source but I invested a couple days into understanding the code now and I would like to at least get this to work. I like to split out config.h and pins.h as it brings a lot of order into the chaos. @seandepagnier What rudder values does pypilot expect? I'm sending ADCs over to pypilot but the rudder position only changes between -94 and -88. It's a 10 bit value that I - like you - multiplied by 4. Then I just send out the raw result. How can I change that? How is the the rudder sensor calibration supposed to work? |
Got it. Rudder is a value from 0 to 65535 with 32768 being the center at 0 degrees. Next stop is servo control. The PWM stuff should be working (untested) but when I look at the raw values that autopilot sends out (looking at the Scope) they don't make sense to me, yet. The values expected by the firmware range from 0 to 2000. However, what the scope shows when I move the IMU is 0.8 and -0.8. |
@McNugget6750, I think I'd say the same in your situation :-)
I had thought of doing something like that as a v2, something somewhat kernel-like, that is to say, a
How far along is your development of this idea? Ie, is this aspect of it working now, in the code that's been pushed to your repo? Looking forward to working with you. |
Yes I'm confused by this too. I understand that 1000 is the idle value, but I can't work out whether the number corresponds to some notion of where the rudder is, or whether it's how fast the rudder should be moving (the difference from 1000 being the velocity). Is it that the value was originally that of RC servo position, and the meaning has somewhat changed? @seandepagnier, can you help me understand how this value maps to drivers which aren't an RC servo please?
Good questions. I'd also like to understand this. |
It seems communication is working. I get the rudder position report in Autopilot and can engage. |
Well sure, but working code trumps work in progress. I've had a look at your changes, and it's something I can conceptually work with. But it breaks support for the existing drivers, mostly because lots of the old code is commented out. I do very much like the "explorer's notes" comments you've put into the code. Question: Do you intend for your work to be incorporated back into pypilot soon? (Or were you looking to make a permanent fork?)
I'm tempted to selectively take some of the work you've done, the parts that don't break the current support for drivers, and put those changes into my own fork, with the intention of passing them back to pypilot. Thoughts? @seandepagnier, it would be good to get your feelings on this. Mitch. |
I have bought a small servo and I'll try out my code on it soon. |
Generally, I think that's a good idea. However, to be honest: Keeping the original code alive with support for a bare metal H-bridge with essentially no self protection seems a bit like keeping code for a floppy disk drive alive even though no one will ever use it again. The spectrum of off the shelve h-bridge hardware is so large and this code is very complex only because of obsolete hardware. |
I would love for this to go back into public domain and therefore be available to PyPilot users. However, if I have to, I would go and leave this a permanent fork. But I'd rather integrate it back into the PyPilot. |
@seandepagnier I hope you don't get my comments and questions the wrong way! Without you, all this wouldn't exist! |
Hi Timo,
I agree, but I will wait for @seandepagnier's thoughts.
I feel the same.
pypilot.org says that PyPilot is covered by the GPL3 license (and see for example, the top of |
The point of Sean's pypilot was to be very efficient, use of energy and reduce unnecessary movement. Taking a meat cleaver to it will change that advantage. IMHO |
I dont think you understand what Sean has done here. |
Side view - looks like you guys are doing right thing, but it is going little far from original code means it is not the seandepagnier code any more. Nobody keep us from make ‘right’ motorV2 implementation and put it next to motor.ino directory and have Two versions of the motor controllers. Or just keep in your repository and MAINTAIN it, if it is better people will use it. I respect seandepagnier and his effort to design and MAINTAIN WORKING pypilot, every code has its history, and when you see from the side YOU THINK you can do it better, so, do it better, share with people. The best part of current motor.ino code IT IS WORKING, AND WORK STABLE. NOTHIG PERSONAL, JUST THOUGHTS IN LOUD |
@rgleason you are right. I'm sure I haven't understood what @seandepagnier has done, yet. It's an immense amount of work he put into this and I came in and could not find a starting point. As you can see from @CapnKernel and my questions, we're far from understanding how the complete system works. I'm just concentrating on the motor driver and the hope is to make it more modular and more accessible in case people need to add hardware support. @partyvi I agree with you. It's a well known principle: "Not invented here" hits basically everyone and I'm well aware of it. It basically means that one developer very easily falls into the trap of saying another one's code/product is bad - just because he did not invent it himself. |
I completely understand the need to modify and tweak my code to suit your needs as the resulting software will remain GPL! I would like to support configuring the driver at compile time, however with DRIVER==GENERIC meaning to use the current io strapping arrangement so it works on existing hardware. Other drivers can use these io pins for other arrangements or purposes. As far as driving h bridge directly instead of using a module: What is the cost and on resistance of your driver? We should compare these factors when considering what is obsolete. Don't get too caught up in motor.ino: the future drivers will be brushless anyway. |
This piece I really haven't understood, yet. The power savings options. |
I apologize, I misspoke: I meant open source, not public domain. I realize there are legal differences between GPL and public domain. Sean, in order to either stop me from building my own version of the motor controller and to help others getting started easier, I think it makes sense to create documentation for your original code. Regarding brushless: I'm all for it. However, the driver motor is something a lot of people might already have. I am building this to drive a 35 year old hydraulic servo pump on my Uniflight 42. Going brushless only really works on scratch builds. No? |
Reducing the cpu speed to 4mhz was done not for power saving but for improved analog sampling of the current feedback. A side benefit is it does save a few milliamps. The voltage regulator and as mentioned LEDS waste a lot of power. I have a new version of hardware to run the avr at 3.3v and cut idle current down hopefully to 4-5mA from 15mA. Why does it matter? Because you could leave the controller powered for weeks not using it, it should not be an energy waste. There are schematics available already: If there are several supported schematics can we post links to them for each driver? As for commenting and renaming the code, I don't see any problems as long as no functional changes are made. Changing something can inadvertently cause unexplained behavior elsewhere, and as mentioned before this code seems to be "stable" Reordering a few instructions and it would not be. As for brushless controllers, they can already drive brushed motors which is supported in a lot of software so this is really the future controller. I went with brushed because of all the existing motors, the electronics are slightly cheaper and the controller logic much simpler. |
@seandepagnier Hey Sean, I'm trying to register in the forum (http://forum.openmarine.net/) but for days I have been waiting for several activation emails. Since you're a MOD, could you please do me a favor and take a look? My username is McNugget. I'll delete this message after. |
Done, try now. |
Excellent, thank you! |
Motor control works and rudder feedback works!
Since the code is not using any timers manually, I was able to quickly integrate a TFT display library to give me some simple debugging interface as well. I must admit, 1khz PWM is quite beepy. Maybe we call this a power boat branch and not a sail across the Atlantic branch. When an engine is running, I won't be able to hear it. Under sails, that's a different question. |
Since the update to OpenPlotter 1.2 Alpha the rudder value that's being displayed in the scope only goes from -45 to +45. Before, it went from -100 to +100. Did that change in OP? Did I change something and didn't realize? |
@sailoog I can view the forum now but when I post an issue (GPS baud rates > 4800 seem to crash the GPS and sometimes the entire serial monitor), my post never shows up. Is the post waiting for moderator approval? |
Yes, the first post is always moderated |
Hi,
On Thu, Dec 5, 2019 at 10:30 AM Timo ***@***.***> wrote:
The following is working at the moment:
Nice.
This branch is 8 commits ahead, 35 commits behind pypilot:master.
I'm interested to try it. Can you please pull the latest changes from the
main pypilot repo?
|
The last changes I saw, made by @seandepagnier, were only refactoring a few items as far as I recall. If you want to check out my modifications, it makes sense to do it without me pulling changes. |
@CapnKernel I am reading up on pulling changes from the parent repository into my fork. I haven't done this before and since I made extensive changes to the code, I am concerned it will break something in the process. That's why I'm a bit reluctant :) |
I merged the changes. If you test the code and find issues, please post them in the other repository. I have been spamming this "issue" enough. |
@seandepagnier Two questions:
|
The motor controller does not know about port and starboard. The
rudder feedback value is raw, and min and max limits are set. If the
min and max are flipped, then the logic is reversed, so rudder
feedback will work with increasing counts to either port and
starboard.
The actual rudder calibration is performed in python, and the sign of
the scale factor indicates if increasing voltage is port or starboard.
…On 12/6/19, Timo ***@***.***> wrote:
@seandepagnier Two questions:
- Rudder sensor feedback > 32768: rudder is further PORT or STARBOARD?
- motor command to motor.ino >1000: move rudder towards PORT or STARBOARD?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#37 (comment)
|
On Sun, Dec 8, 2019 at 1:22 AM seandepagnier ***@***.***> wrote:
The motor controller does not know about port and starboard. The
rudder feedback value is raw, and min and max limits are set. If the
min and max are flipped, then the logic is reversed
I'm thinking this should go straight into a doc. Timo? 😀
|
i’m not sure why, but during my test run that I’m conducting right now, the auto pilot is steering in the wrong direction. When it should turn right steers left. When it should steer left it steers right. however, when I use the buttons on the pypilot GUI port and starboard is correct. How can I change this behavior? |
For now, I have swapped the behavior for port and starboard on the motor controller side. That seems to work. But that means the buttons in the gui are reversered for pure manual control. EDIT: Course following works and I even had the chance to tune the PID controller! I'm extremely excited right now! However, I really want to get the GPS route waypoint following to work as stated here: http://forum.openmarine.net/showthread.php?tid=2134 |
Which gui do you mean? There are several control interfaces.
You can also give the servo a negative gain instead of swapping the wires.
…On 12/8/19, Timo ***@***.***> wrote:
For now, I have swapped the behavior for port and starboard on the motor
controller side. That seems to work. But that means the buttons in the gui
are reversered for pure manual control.
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#37 (comment)
|
Just activate the route and ensure opencpn outputs apb sentences to a
tcp connection to pypilot on port 20220.
Sean
…On 12/8/19, Timo ***@***.***> wrote:
In this gui, started by OpenCPN the buttons for port and starboard are now
reversed:
![image](https://user-images.githubusercontent.com/12099353/70402795-750bbf80-19e9-11ea-9741-7b0968d2c6ed.png)
But when I engage the autopilot in either compas or GPS mode, the buttons to
change course are now working!
![image](https://user-images.githubusercontent.com/12099353/70402836-98366f00-19e9-11ea-822f-340796f77552.png)
However, now that I can keep a course with reasonable precision, I really
want to get waypoint following to work. I can't seem to find the setting
that allows openCPN to communicate the next waypoint to pypilot.
What are the steps I need to take to enable waypoint following?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#37 (comment)
|
That seems to be the secret ingredient that I can’t figure out. I know where to set it up but I don’t know what pypilot’s IP is. If the connection is set up correctly and the route is active, I should see APB messages in the NMEA debug window, correct? |
apb mesages.
If the plugin is working you must have pypilot ip set correctly there.
…On 12/8/19, Timo ***@***.***> wrote:
That seems to be the secret ingredient that I can’t figure out. I know where
to set it up but I don’t know what pypilot’s IP is. If the connection is set
up correctly and the route is active, I should see APD messages in the NMEA
debug window, correct?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#37 (comment)
|
you need to use the address of where pypilot is running. This really
depends on the network setup and how you run pypilot.
…On 12/8/19, Timo ***@***.***> wrote:
I fear you mean what I needed to set up under connections. There I put
localhost there and it works. But it’s only set up as an input.
Then, based on this other success report, I tried 192.168.14.1 as well as
10.10.10.1 with input and output and both didn’t work:
![5F385122-E4BA-41CA-9A0C-3FFFC332BCC6](https://user-images.githubusercontent.com/12099353/70406517-dc2f7100-19f5-11ea-8890-f27330607bc0.jpeg)
Are you saying, I should just set localhost up as input AND output and
that’s it?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#37 (comment)
|
Everything works! I apologize for my brain fart regarding the IP addresses. Obviously, because everything runs on the Raspberry Pi, localhost does it all. Also, I flipped a bit on the port number, which is 20220 and not 20200. Thank you all for the help! |
I found the same thing: Either I can have the left button in standby mode turn the boat to port, but in autopilot mode, PyPilot just drives the boat further and further off course, or by switching the wires, the autopilot works but the left and right buttons work backwards, ie, not useful. @McNugget6750, did you find the cause? |
Hi there,
I love how much work has been put into this all to make this work and open source.
The whole day, I have been reading the Arduino code for the motor driver and added a ton of documentation, changed the layout a little bit and organized the code based on configuration and pin assignments as well as important stuff at the top and tools etc. at the bottom of the file.
However, I wonder, why you are using all the AVR native functions and not the Arduino build in libraries. Is it really necessary to drive this at 60Hz? Is it really necessary to run certain things at exactly 30Hz? Or 50Hz?
Why did you decide to configure the code by using external jumpers if the code needs to be modified to fit ones needs anyways?
I guess I would like to propose to make this a bit more modular. I want to implement compatibility with the IBT 2 H-BRIDGE. It's cheap and powerful but it needs two PWM and two enable lines but it also provides two current sense / fault lines. Integrating this into your code seems incredibly complex as it requires detailed knowledge of the AVR timers. It looks like I can't just use analogWrite() to do this because you're running custom timers.
If this code could be restructured to use #defines in a config.h to do the general configuration, a pins.h to do all pin assignments and remove all the #if 1 or #if 0 ... #endif stuff, and removal of all the custom timers, it would already help a lot. At present, without further documentation, I would love to rewrite all this to use standard Arduino functions instead of lowest level AVR code. I mean, who really uses a bare metal H-Bridge these days that would require all this in the first place?
Please don't take this the wrong way! I know people are using and loving your work! And I'm here for a reason: I want to use OpenPlotter and PyPilot, too! However, in order to make this motor driver more modifiable, we need to clean up the code and write more documentation :)
The text was updated successfully, but these errors were encountered: