From 109b2c92c4c79c877b33641e7a4c63b6875a080d Mon Sep 17 00:00:00 2001 From: Cole Deck Date: Wed, 13 Sep 2023 11:30:59 -0500 Subject: [PATCH] Add sabertooth lib, start enabling all motor drive --- lib/Sabertooth/changes.txt | 37 ++ .../examples/1.Basics/Jolty/Jolty.ino | 46 +++ .../examples/1.Basics/Sweep/Sweep.ino | 53 +++ .../TankStyleSweep/TankStyleSweep.ino | 69 ++++ .../2.Settings/MinVoltage/MinVoltage.ino | 34 ++ .../Persistent/BaudRate/BaudRate.ino | 48 +++ .../Persistent/Deadband/Deadband.ino | 33 ++ .../Persistent/MaxVoltage/MaxVoltage.ino | 41 +++ .../2.Settings/Persistent/Ramping/Ramping.ino | 39 ++ .../SerialTimeout/SerialTimeout.ino | 33 ++ .../3.Advanced/SharedLine/SharedLine.ino | 43 +++ .../SoftwareSerial/SoftwareSerial.ino | 35 ++ lib/Sabertooth/keywords.txt | 22 ++ lib/Sabertooth/license.txt | 7 + lib/Sabertooth/src/Sabertooth.cpp | 142 +++++++ lib/Sabertooth/src/Sabertooth.h | 179 +++++++++ .../src/SabertoothArduinoLibrary.chm | Bin 0 -> 94614 bytes platformio.ini | 5 + src/main.cpp | 346 +++++++++++++++--- 19 files changed, 1158 insertions(+), 54 deletions(-) create mode 100644 lib/Sabertooth/changes.txt create mode 100644 lib/Sabertooth/examples/1.Basics/Jolty/Jolty.ino create mode 100644 lib/Sabertooth/examples/1.Basics/Sweep/Sweep.ino create mode 100644 lib/Sabertooth/examples/1.Basics/TankStyleSweep/TankStyleSweep.ino create mode 100644 lib/Sabertooth/examples/2.Settings/MinVoltage/MinVoltage.ino create mode 100644 lib/Sabertooth/examples/2.Settings/Persistent/BaudRate/BaudRate.ino create mode 100644 lib/Sabertooth/examples/2.Settings/Persistent/Deadband/Deadband.ino create mode 100644 lib/Sabertooth/examples/2.Settings/Persistent/MaxVoltage/MaxVoltage.ino create mode 100644 lib/Sabertooth/examples/2.Settings/Persistent/Ramping/Ramping.ino create mode 100644 lib/Sabertooth/examples/2.Settings/SerialTimeout/SerialTimeout.ino create mode 100644 lib/Sabertooth/examples/3.Advanced/SharedLine/SharedLine.ino create mode 100644 lib/Sabertooth/examples/3.Advanced/SoftwareSerial/SoftwareSerial.ino create mode 100644 lib/Sabertooth/keywords.txt create mode 100644 lib/Sabertooth/license.txt create mode 100644 lib/Sabertooth/src/Sabertooth.cpp create mode 100644 lib/Sabertooth/src/Sabertooth.h create mode 100644 lib/Sabertooth/src/SabertoothArduinoLibrary.chm diff --git a/lib/Sabertooth/changes.txt b/lib/Sabertooth/changes.txt new file mode 100644 index 0000000..78c2aa3 --- /dev/null +++ b/lib/Sabertooth/changes.txt @@ -0,0 +1,37 @@ +Arduino Libraries for SyRen/Sabertooth +Copyright (c) 2012-2013 Dimension Engineering LLC +http://www.dimensionengineering.com/arduino + +1 July 2013, Version 1.5 +- USB Sabertooth Packet Serial Library + - Initial release. + +1 April 2013, Version 1.4 +- Added documentation. +- Improved support for Arduino Leonardo. +- Packet Serial Library + - Simplified the code to save space and increase readability. + +3 May 2012, Version 1.3 +- Improved compatibility with earlier versions of the Arduino software. + Previous versions required Arduino 1.0 or newer, but this version + should work back to Arduino 0018 (still in use by Debian Linux 6.0) + and possibly earlier. + + If you are using a version of Arduino older than 1.0, you will need + to rename the examples from .ino to .pde to see them in the Examples + menu. + +20 April 2012, Version 1.2 +- Packet Serial Library + - Added a stop() function to match the command set of the Simplified + Serial libraries. + +19 April 2012, Version 1.1 +- Packet Serial Library + - Added a single-argument motor() function as a convenience for SyRen. + +18 April 2012, Version 1.0 +- Initial release. + +Please let us know if you run into any bugs! Thanks and enjoy the library! \ No newline at end of file diff --git a/lib/Sabertooth/examples/1.Basics/Jolty/Jolty.ino b/lib/Sabertooth/examples/1.Basics/Jolty/Jolty.ino new file mode 100644 index 0000000..8fe814f --- /dev/null +++ b/lib/Sabertooth/examples/1.Basics/Jolty/Jolty.ino @@ -0,0 +1,46 @@ +// Jolty Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include + +Sabertooth ST(128); // The Sabertooth is on address 128. We'll name its object ST. + // If you've set up your Sabertooth on a different address, of course change + // that here. For how to configure address, etc. see the DIP Switch Wizard for + // Sabertooth - http://www.dimensionengineering.com/datasheets/SabertoothDIPWizard/start.htm + // SyRen - http://www.dimensionengineering.com/datasheets/SyrenDIPWizard/start.htm + // Be sure to select Packetized Serial Mode for use with this library. + // + // On that note, you can use this library for SyRen just as easily. + // The diff-drive commands (drive, turn) do not work on a SyRen, of course, but it will respond correctly + // if you command motor 1 to do something (ST.motor(1, ...)), just like a Sabertooth. + // + // In this sample, hardware serial TX connects to S1. + // See the SoftwareSerial example in 3.Advanced for how to use other pins. + +void setup() +{ + SabertoothTXPinSerial.begin(9600); // 9600 is the default baud rate for Sabertooth packet serial. + ST.autobaud(); // Send the autobaud command to the Sabertooth controller(s). + // NOTE: *Not all* Sabertooth controllers need this command. + // It doesn't hurt anything, but V2 controllers use an + // EEPROM setting (changeable with the function setBaudRate) to set + // the baud rate instead of detecting with autobaud. + // + // If you have a 2x12, 2x25 V2, 2x60 or SyRen 50, you can remove + // the autobaud line and save yourself two seconds of startup delay. +} + + +void loop() +{ + ST.motor(1, 127); // Go forward at full power. + delay(2000); // Wait 2 seconds. + ST.motor(1, 0); // Stop. + delay(2000); // Wait 2 seconds. + ST.motor(1, -127); // Reverse at full power. + delay(2000); // Wait 2 seconds. + ST.motor(1, 0); // Stop. + delay(2000); +} + diff --git a/lib/Sabertooth/examples/1.Basics/Sweep/Sweep.ino b/lib/Sabertooth/examples/1.Basics/Sweep/Sweep.ino new file mode 100644 index 0000000..4d5cba1 --- /dev/null +++ b/lib/Sabertooth/examples/1.Basics/Sweep/Sweep.ino @@ -0,0 +1,53 @@ +// Sweep Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include + +Sabertooth ST(128); // The Sabertooth is on address 128. We'll name its object ST. + // If you've set up your Sabertooth on a different address, of course change + // that here. For how to configure address, etc. see the DIP Switch Wizard for + // Sabertooth - http://www.dimensionengineering.com/datasheets/SabertoothDIPWizard/start.htm + // SyRen - http://www.dimensionengineering.com/datasheets/SyrenDIPWizard/start.htm + // Be sure to select Packetized Serial Mode for use with this library. + // + // On that note, you can use this library for SyRen just as easily. + // The diff-drive commands (drive, turn) do not work on a SyRen, of course, but it will respond correctly + // if you command motor 1 to do something (ST.motor(1, ...)), just like a Sabertooth. + // + // In this sample, hardware serial TX connects to S1. + // See the SoftwareSerial example in 3.Advanced for how to use other pins. + +void setup() +{ + SabertoothTXPinSerial.begin(9600); // 9600 is the default baud rate for Sabertooth packet serial. + ST.autobaud(); // Send the autobaud command to the Sabertooth controller(s). + // NOTE: *Not all* Sabertooth controllers need this command. + // It doesn't hurt anything, but V2 controllers use an + // EEPROM setting (changeable with the function setBaudRate) to set + // the baud rate instead of detecting with autobaud. + // + // If you have a 2x12, 2x25 V2, 2x60 or SyRen 50, you can remove + // the autobaud line and save yourself two seconds of startup delay. +} + +void loop() +{ + int power; + + // Ramp motor 1 from -127 to 127 (full reverse to full forward), + // waiting 20 ms (1/50th of a second) per value. + for (power = -127; power <= 127; power ++) + { + ST.motor(1, power); + delay(20); + } + + // Now go back the way we came. + for (power = 127; power >= -127; power --) + { + ST.motor(1, power); // Tip for SyRen users: Typing ST.motor(power) does the same thing as ST.motor(1, power). + delay(20); // Since SyRen doesn't have a motor 2, this alternative can save you typing. + } +} + diff --git a/lib/Sabertooth/examples/1.Basics/TankStyleSweep/TankStyleSweep.ino b/lib/Sabertooth/examples/1.Basics/TankStyleSweep/TankStyleSweep.ino new file mode 100644 index 0000000..e9956e6 --- /dev/null +++ b/lib/Sabertooth/examples/1.Basics/TankStyleSweep/TankStyleSweep.ino @@ -0,0 +1,69 @@ +// Tank-Style Sweep Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include + +// Mixed mode is for tank-style diff-drive robots. + +Sabertooth ST(128); // The Sabertooth is on address 128. We'll name its object ST. + // If you've set up your Sabertooth on a different address, of course change + // that here. For how to configure address, etc. see the DIP Switch Wizard for + // Sabertooth - http://www.dimensionengineering.com/datasheets/SabertoothDIPWizard/start.htm + // SyRen - http://www.dimensionengineering.com/datasheets/SyrenDIPWizard/start.htm + // Be sure to select Packetized Serial Mode for use with this library. + // + // This sample uses the mixed mode (diff-drive) commands, which require two motors + // and hence do not work on a SyRen. + // + // In this sample, hardware serial TX connects to S1. + // See the SoftwareSerial example in 3.Advanced for how to use other pins. + +void setup() +{ + SabertoothTXPinSerial.begin(9600); // 9600 is the default baud rate for Sabertooth packet serial. + ST.autobaud(); // Send the autobaud command to the Sabertooth controller(s). + // NOTE: *Not all* Sabertooth controllers need this command. + // It doesn't hurt anything, but V2 controllers use an + // EEPROM setting (changeable with the function setBaudRate) to set + // the baud rate instead of detecting with autobaud. + // + // If you have a 2x12, 2x25 V2, 2x60 or SyRen 50, you can remove + // the autobaud line and save yourself two seconds of startup delay. + + ST.drive(0); // The Sabertooth won't act on mixed mode packet serial commands until + ST.turn(0); // it has received power levels for BOTH throttle and turning, since it + // mixes the two together to get diff-drive power levels for both motors. +} + +// The SLOW ramp here is turning, and the FAST ramp is throttle. +// If that's the opposite of what you're seeing, swap M2A and M2B. +void loop() +{ + int power; + + // Don't turn. Ramp from going backwards to going forwards, waiting 20 ms (1/50th of a second) per value. + for (power = -127; power <= 127; power ++) + { + ST.drive(power); + delay(20); + } + + // Now, let's use a power level of 20 (out of 127) forward. + // This way, our turning will have a radius. + ST.drive(20); + + // Ramp turning from full left to full right SLOWLY by waiting 50 ms (1/20th of a second) per value. + for (power = -127; power <= 127; power ++) + { + ST.turn(power); + delay(50); + } + + // Now stop turning, and stop driving. + ST.turn(0); + ST.drive(0); + + // Wait a bit. This is so you can catch your robot if you want to. :-) + delay(5000); +} diff --git a/lib/Sabertooth/examples/2.Settings/MinVoltage/MinVoltage.ino b/lib/Sabertooth/examples/2.Settings/MinVoltage/MinVoltage.ino new file mode 100644 index 0000000..ef5b016 --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/MinVoltage/MinVoltage.ino @@ -0,0 +1,34 @@ +// Set Minimum Voltage Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +// The values in this sample are specifically for the Sabertooth 2x25, and may +// not have the same effect on other models. +#include + +Sabertooth ST(128); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + ST.autobaud(); + + // This setting does not persist between power cycles. + // See the Packet Serial section of the documentation for what values to use + // for the minimum voltage command. It may vary between Sabertooth models + // (2x25, 2x60, etc.). + // + // On a Sabertooth 2x25, the value is (Desired Volts - 6) X 5. + // So, in this sample, we'll make the low battery cutoff 12V: (12 - 6) X 5 = 30. + ST.setMinVoltage(30); +} + +void loop() +{ + ST.motor(1, 50); + delay(5000); + + ST.motor(1, -50); + delay(5000); +} + diff --git a/lib/Sabertooth/examples/2.Settings/Persistent/BaudRate/BaudRate.ino b/lib/Sabertooth/examples/2.Settings/Persistent/BaudRate/BaudRate.ino new file mode 100644 index 0000000..b7f416a --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/Persistent/BaudRate/BaudRate.ino @@ -0,0 +1,48 @@ +// Set Baud Rate Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +// WARNING: This sample makes changes that will persist between restarts. +// NOTE: The setBaudRate function will only have an effect on V2 controllers (2x12, 2x25 V2, 2x60, SyRen 50). +// Earlier controllers automatically detect the baud rate you choose in Serial.begin +// when you call the autobaud function. Autobaud was replaced in V2 controllers for reliability +// in the event that the Sabertooth lost power. +#include + +Sabertooth ST(128); + +void setup() +{ + // This sample will tell the Sabertooth *at 9600 baud* to *switch to 2400 baud*. + // Keep in mind you must send the command to change the baud rate *at the baud rate + // the Sabertooth is listening at* (factory default is 9600). After that, if it works, + // you will be able to communicate using the new baud rate. + // + // Options are: + // 2400 + // 9600 + // 19200 + // 38400 + // 115200 (only supported by some devices such as 2X60 -- check the device's datasheet) + // + // WARNING: The Sabertooth remembers this command between restarts. + // To change your Sabertooth back to its default, you must *be at the baud rate you've + // set the Sabertooth to*, and then call ST.setBaudRate(9600) + SabertoothTXPinSerial.begin(9600); + ST.setBaudRate(2400); + SabertoothTXPinSerial.end(); + + // OK, we're at 2400. Let's talk to the Sabertooth at that speed. + SabertoothTXPinSerial.begin(2400); +} + +void loop() +{ + ST.drive(0); + ST.turn(20); + delay(2000); + + ST.turn(-20); + delay(2000); +} + diff --git a/lib/Sabertooth/examples/2.Settings/Persistent/Deadband/Deadband.ino b/lib/Sabertooth/examples/2.Settings/Persistent/Deadband/Deadband.ino new file mode 100644 index 0000000..28a986c --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/Persistent/Deadband/Deadband.ino @@ -0,0 +1,33 @@ +// Set Deadband Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +// WARNING: This sample makes changes that will persist between restarts AND in all modes. +#include + +Sabertooth ST(128); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + ST.autobaud(); + + // This makes the deadband from -20 to 20 (of 127). + // If your commands for a motor stay entirely within the deadband for more than + // a second, the motor driver will stop the motor. + // WARNING: The Sabertooth remembers this command between restarts AND in all modes. + // To change your Sabertooth back to its default, call ST.setDeadband(0) + ST.setDeadband(20); +} + +void loop() +{ + // 50 is greater than 20, so the motor moves. + ST.motor(1, 50); + delay(5000); + + // 10 is NOT, so the motor does not move. + ST.motor(1, 10); + delay(5000); +} + diff --git a/lib/Sabertooth/examples/2.Settings/Persistent/MaxVoltage/MaxVoltage.ino b/lib/Sabertooth/examples/2.Settings/Persistent/MaxVoltage/MaxVoltage.ino new file mode 100644 index 0000000..d19ab19 --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/Persistent/MaxVoltage/MaxVoltage.ino @@ -0,0 +1,41 @@ +// Set Maximum Voltage Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +// WARNING: This sample makes changes that will persist between restarts AND in all modes. +// The values in this sample are specifically for the Sabertooth 2x25, and may +// not have the same effect on other models. +#include + +Sabertooth ST(128); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + ST.autobaud(); + + // See the Packet Serial section of the documentation for what values to use + // for the maximum voltage command. It may vary between Sabertooth models + // (2x25, 2x60, etc.). + // + // On a Sabertooth 2x25, the value is (Desired Volts) X 5.12. + // In this sample, we'll cap the max voltage before the motor driver does + // a hard brake at 14V. For a 12V ATX power supply this might be reasonable -- + // at 16V they tend to shut off. Here, if the voltage climbs above + // 14V due to regenerative braking, the Sabertooth will go into hard brake instead. + // While this is occuring, the red Error LED will turn on. + // + // 14 X 5.12 = 71.68, so we'll go with 71, cutting off slightly below 14V. + // + // WARNING: This setting persists between power cycles. + ST.setMaxVoltage(71); +} + +void loop() +{ + ST.motor(1, 50); + delay(5000); + + ST.motor(1, -50); + delay(5000); +} diff --git a/lib/Sabertooth/examples/2.Settings/Persistent/Ramping/Ramping.ino b/lib/Sabertooth/examples/2.Settings/Persistent/Ramping/Ramping.ino new file mode 100644 index 0000000..56fbc95 --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/Persistent/Ramping/Ramping.ino @@ -0,0 +1,39 @@ +// Set Ramping Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +// WARNING: This sample makes changes that will persist between restarts AND in all modes. +#include + +Sabertooth ST(128); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + ST.autobaud(); + + // See the Sabertooth 2x60 documentation for information on ramping values. + // There are three ranges: 1-10 (Fast), 11-20 (Slow), and 21-80 (Intermediate). + // The ramping value 14 used here sets a ramp time of 4 seconds for full + // forward-to-full reverse. + // + // 0 turns off ramping. Turning off ramping requires a power cycle. + // + // WARNING: The Sabertooth remembers this command between restarts AND in all modes. + // To change your Sabertooth back to its default, call ST.setRamping(0) + ST.setRamping(14); +} + +void loop() +{ + // Full forward, both motors. + ST.motor(1, 127); + ST.motor(2, 127); + delay(5000); + + // Full reverse + ST.motor(1, -127); + ST.motor(2, -127); + delay(5000); +} + diff --git a/lib/Sabertooth/examples/2.Settings/SerialTimeout/SerialTimeout.ino b/lib/Sabertooth/examples/2.Settings/SerialTimeout/SerialTimeout.ino new file mode 100644 index 0000000..6c93fa2 --- /dev/null +++ b/lib/Sabertooth/examples/2.Settings/SerialTimeout/SerialTimeout.ino @@ -0,0 +1,33 @@ +// Set Serial Timeout Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include + +Sabertooth ST(128); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + ST.autobaud(); + + // setTimeout rounds up to the nearest 100 milliseconds, so this 950 will actually be 1 second. + // A value of 0 disables the serial timeout. + ST.setTimeout(950); +} + +void loop() +{ + // Set motor 1 to reverse 20 (out of 127), and sleep for 5 seconds. + // Notice how it cuts out after 1 second -- this is the serial timeout in action. + // Since we configured it in setup() for 1 second, 1 second without any new + // commands will cause the motors to stop. + ST.motor(1, -20); + delay(5000); + + // Why do this? + // If the S1 wire gets cut for some reason, or if your program crashes, + // the Sabertooth will stop receiving commands from the Arduino. + // With a timeout, your robot will stop. So, it's a safety feature mostly. +} + diff --git a/lib/Sabertooth/examples/3.Advanced/SharedLine/SharedLine.ino b/lib/Sabertooth/examples/3.Advanced/SharedLine/SharedLine.ino new file mode 100644 index 0000000..6f029d7 --- /dev/null +++ b/lib/Sabertooth/examples/3.Advanced/SharedLine/SharedLine.ino @@ -0,0 +1,43 @@ +// Shared Line Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include + +// Up to 8 Sabertooth/SyRen motor drivers can share the same S1 line. +// This sample uses three: address 128 and 129 on ST1[0] and ST1[2], +// and address 130 on ST2. +Sabertooth ST1[2] = { Sabertooth(128), Sabertooth(129) }; +Sabertooth ST2(130); + +void setup() +{ + SabertoothTXPinSerial.begin(9600); + Sabertooth::autobaud(SabertoothTXPinSerial); // Autobaud is for the whole serial line -- you don't need to do + // it for each individual motor driver. This is the version of + // the autobaud command that is not tied to a particular + // Sabertooth object. + // See the examples in 1.Basics for information on whether you + // need this line at all. +} + +void loop() +{ + // ST1[0] (address 128) has power 50 (of 127 max) on M1, + // ST1[1] (address 129) has power 60 (of 127 max) on M2, and + // ST2 (address 130) we'll do tank-style and have it drive 20 and turn right 50. + // Do this for 5 seconds. + ST1[0].motor(1, 50); + ST1[1].motor(2, 60); + ST2.drive(20); + ST2.turn(50); + delay(5000); + + // And now let's stop for 5 seconds, except address 130 -- we'll let it stop and turn left... + ST1[0].motor(1, 0); + ST1[1].motor(2, 0); + ST2.drive(0); + ST2.turn(-40); + delay(5000); +} + diff --git a/lib/Sabertooth/examples/3.Advanced/SoftwareSerial/SoftwareSerial.ino b/lib/Sabertooth/examples/3.Advanced/SoftwareSerial/SoftwareSerial.ino new file mode 100644 index 0000000..1e6d61c --- /dev/null +++ b/lib/Sabertooth/examples/3.Advanced/SoftwareSerial/SoftwareSerial.ino @@ -0,0 +1,35 @@ +// Software Serial Sample for Packet Serial +// Copyright (c) 2012 Dimension Engineering LLC +// See license.txt for license details. + +#include +#include + +SoftwareSerial SWSerial(NOT_A_PIN, 11); // RX on no pin (unused), TX on pin 11 (to S1). +Sabertooth ST(128, SWSerial); // Address 128, and use SWSerial as the serial port. + +void setup() +{ + SWSerial.begin(9600); + ST.autobaud(); +} + +void loop() +{ + int power; + + // Ramp from -127 to 127 (full reverse to full forward), waiting 20 ms (1/50th of a second) per value. + for (power = -127; power <= 127; power ++) + { + ST.motor(1, power); + delay(20); + } + + // Now go back the way we came. + for (power = 127; power >= -127; power --) + { + ST.motor(1, power); + delay(20); + } +} + diff --git a/lib/Sabertooth/keywords.txt b/lib/Sabertooth/keywords.txt new file mode 100644 index 0000000..b29c75d --- /dev/null +++ b/lib/Sabertooth/keywords.txt @@ -0,0 +1,22 @@ +# Syntax Coloring for the Sabertooth Library + +# Classes +Sabertooth KEYWORD1 + +# Sabertooth methods +address KEYWORD2 +port KEYWORD2 +autobaud KEYWORD2 + +# Common methods +command KEYWORD2 +motor KEYWORD2 +drive KEYWORD2 +turn KEYWORD2 +setMinVoltage KEYWORD2 +setMaxVoltage KEYWORD2 +setBaudRate KEYWORD2 +setDeadband KEYWORD2 +setRamping KEYWORD2 +setTimeout KEYWORD2 +stop KEYWORD2 diff --git a/lib/Sabertooth/license.txt b/lib/Sabertooth/license.txt new file mode 100644 index 0000000..c1eb6d8 --- /dev/null +++ b/lib/Sabertooth/license.txt @@ -0,0 +1,7 @@ +Arduino Libraries for SyRen/Sabertooth +Copyright (c) 2012-2013 Dimension Engineering LLC +http://www.dimensionengineering.com/arduino + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/lib/Sabertooth/src/Sabertooth.cpp b/lib/Sabertooth/src/Sabertooth.cpp new file mode 100644 index 0000000..de7dc5e --- /dev/null +++ b/lib/Sabertooth/src/Sabertooth.cpp @@ -0,0 +1,142 @@ +/* +Arduino Library for SyRen/Sabertooth Packet Serial +Copyright (c) 2012-2013 Dimension Engineering LLC +http://www.dimensionengineering.com/arduino + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "Sabertooth.h" + +Sabertooth::Sabertooth(byte address) + : _address(address), _port(SabertoothTXPinSerial) +{ + +} + +Sabertooth::Sabertooth(byte address, SabertoothStream& port) + : _address(address), _port(port) +{ + +} + +void Sabertooth::autobaud(boolean dontWait) const +{ + autobaud(port(), dontWait); +} + +void Sabertooth::autobaud(SabertoothStream& port, boolean dontWait) +{ + if (!dontWait) { delay(1500); } + port.write(0xAA); +#if defined(ARDUINO) && ARDUINO >= 100 + port.flush(); +#endif + if (!dontWait) { delay(500); } +} + +void Sabertooth::command(byte command, byte value) const +{ + port().write(address()); + port().write(command); + port().write(value); + port().write((address() + command + value) & 0b01111111); +} + +void Sabertooth::throttleCommand(byte command, int power) const +{ + power = constrain(power, -126, 126); + this->command(command, (byte)abs(power)); +} + +void Sabertooth::motor(int power) const +{ + motor(1, power); +} + +void Sabertooth::motor(byte motor, int power) const +{ + if (motor < 1 || motor > 2) { return; } + throttleCommand((motor == 2 ? 4 : 0) + (power < 0 ? 1 : 0), power); +} + +void Sabertooth::drive(int power) const +{ + throttleCommand(power < 0 ? 9 : 8, power); +} + +void Sabertooth::turn(int power) const +{ + throttleCommand(power < 0 ? 11 : 10, power); +} + +void Sabertooth::stop() const +{ + motor(1, 0); + motor(2, 0); +} + +void Sabertooth::setMinVoltage(byte value) const +{ + command(2, (byte)min(value, 120)); +} + +void Sabertooth::setMaxVoltage(byte value) const +{ + command(3, (byte)min(value, 127)); +} + +void Sabertooth::setBaudRate(long baudRate) const +{ +#if defined(ARDUINO) && ARDUINO >= 100 + port().flush(); +#endif + + byte value; + switch (baudRate) + { + case 2400: value = 1; break; + case 9600: default: value = 2; break; + case 19200: value = 3; break; + case 38400: value = 4; break; + case 115200: value = 5; break; + } + command(15, value); + +#if defined(ARDUINO) && ARDUINO >= 100 + port().flush(); +#endif + + // (1) flush() does not seem to wait until transmission is complete. + // As a result, a Serial.end() directly after this appears to + // not always transmit completely. So, we manually add a delay. + // (2) Sabertooth takes about 200 ms after setting the baud rate to + // respond to commands again (it restarts). + // So, this 500 ms delay should deal with this. + delay(500); +} + +void Sabertooth::setDeadband(byte value) const +{ + command(17, (byte)min(value, 127)); +} + +void Sabertooth::setRamping(byte value) const +{ + command(16, (byte)constrain(value, 0, 80)); +} + +void Sabertooth::setTimeout(int milliseconds) const +{ + command(14, (byte)((constrain(milliseconds, 0, 12700) + 99) / 100)); +} diff --git a/lib/Sabertooth/src/Sabertooth.h b/lib/Sabertooth/src/Sabertooth.h new file mode 100644 index 0000000..79d3915 --- /dev/null +++ b/lib/Sabertooth/src/Sabertooth.h @@ -0,0 +1,179 @@ +/* +Arduino Library for SyRen/Sabertooth Packet Serial +Copyright (c) 2012-2013 Dimension Engineering LLC +http://www.dimensionengineering.com/arduino + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef Sabertooth_h +#define Sabertooth_h + +#if defined(ARDUINO) && ARDUINO >= 100 +#include +typedef Stream SabertoothStream; +#else +#include +typedef Print SabertoothStream; +#endif + +#if defined(USBCON) +#define SabertoothTXPinSerial Serial1 // Arduino Leonardo has TX->1 on Serial1, not Serial. +#else +#define SabertoothTXPinSerial Serial +#endif +#define SyRenTXPinSerial SabertoothTXPinSerial + +/*! +\class Sabertooth +\brief Controls a %Sabertooth or %SyRen motor driver running in Packet Serial mode. +*/ +class Sabertooth +{ +public: + /*! + Initializes a new instance of the Sabertooth class. + The driver address is set to the value given, and the Arduino TX serial port is used. + \param address The driver address. + */ + Sabertooth(byte address); + + /*! + Initializes a new instance of the Sabertooth class. + The driver address is set to the value given, and the specified serial port is used. + \param address The driver address. + \param port The port to use. + */ + Sabertooth(byte address, SabertoothStream& port); + +public: + /*! + Gets the driver address. + \return The driver address. + */ + inline byte address() const { return _address; } + + /*! + Gets the serial port. + \return The serial port. + */ + inline SabertoothStream& port() const { return _port; } + + /*! + Sends the autobaud character. + \param dontWait If false, a delay is added to give the driver time to start up. + */ + void autobaud(boolean dontWait = false) const; + + /*! + Sends the autobaud character. + \param port The port to use. + \param dontWait If false, a delay is added to give the driver time to start up. + */ + static void autobaud(SabertoothStream& port, boolean dontWait = false); + + /*! + Sends a packet serial command to the motor driver. + \param command The number of the command. + \param value The command's value. + */ + void command(byte command, byte value) const; + +public: + /*! + Sets the power of motor 1. + \param power The power, between -127 and 127. + */ + void motor(int power) const; + + /*! + Sets the power of the specified motor. + \param motor The motor number, 1 or 2. + \param power The power, between -127 and 127. + */ + void motor(byte motor, int power) const; + + /*! + Sets the driving power. + \param power The power, between -127 and 127. + */ + void drive(int power) const; + + /*! + Sets the turning power. + \param power The power, between -127 and 127. + */ + void turn(int power) const; + + /*! + Stops. + */ + void stop() const; + +public: + /*! + Sets the minimum voltage. + \param value The voltage. The units of this value are driver-specific and are specified in the Packet Serial chapter of the driver's user manual. + */ + void setMinVoltage(byte value) const; + + /*! + Sets the maximum voltage. + Maximum voltage is stored in EEPROM, so changes persist between power cycles. + \param value The voltage. The units of this value are driver-specific and are specified in the Packet Serial chapter of the driver's user manual. + */ + void setMaxVoltage(byte value) const; + + /*! + Sets the baud rate. + Baud rate is stored in EEPROM, so changes persist between power cycles. + \param baudRate The baud rate. This can be 2400, 9600, 19200, 38400, or on some drivers 115200. + */ + void setBaudRate(long baudRate) const; + + /*! + Sets the deadband. + Deadband is stored in EEPROM, so changes persist between power cycles. + \param value The deadband value. + Motor powers in the range [-deadband, deadband] will be considered in the deadband, and will + not prevent the driver from entering nor cause the driver to leave an idle brake state. + 0 resets to the default, which is 3. + */ + void setDeadband(byte value) const; + + /*! + Sets the ramping. + Ramping is stored in EEPROM, so changes persist between power cycles. + \param value The ramping value. Consult the user manual for possible values. + */ + void setRamping(byte value) const; + + /*! + Sets the serial timeout. + \param milliseconds The maximum time in milliseconds between packets. If this time is exceeded, + the driver will stop the motors. This value is rounded up to the nearest 100 milliseconds. + This library assumes the command value is in units of 100 milliseconds. This is true for + most drivers, but not all. Check the packet serial chapter of the driver's user manual + to make sure. + */ + void setTimeout(int milliseconds) const; + +private: + void throttleCommand(byte command, int power) const; + +private: + const byte _address; + SabertoothStream& _port; +}; + +#endif diff --git a/lib/Sabertooth/src/SabertoothArduinoLibrary.chm b/lib/Sabertooth/src/SabertoothArduinoLibrary.chm new file mode 100644 index 0000000000000000000000000000000000000000..b35a285f581707d130eb9c3d4898ddbd9e2741d3 GIT binary patch literal 94614 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 #include #include +#include #include "globals.h" #include #include "MCP3XXX.h" #include "PCF8574.h" +#include "RP2040_ISR_Servo.h" #include "pio_encoder.h" -#include "dumbdisplay.h" -#include "wifidumbdisplay.h" +//#include "dumbdisplay.h" +//#include "wifidumbdisplay.h" #include "zserio.h" #include "SerialUART.h" +#include "Sabertooth.h" const char* ssid = "TEST"; const char* password = "pink4bubble"; -DumbDisplay dumbdisplay(new DDWiFiServerIO(ssid, password), 8192); -LcdDDLayer *optionsdisplay = NULL; -SevenSegmentRowDDLayer *sevenSeg; -JoystickDDLayer *appjoystick; +//DumbDisplay dumbdisplay(new DDWiFiServerIO(ssid, password), 8192); +//LcdDDLayer *optionsdisplay = NULL; +//SevenSegmentRowDDLayer *sevenSeg; +//JoystickDDLayer *appjoystick; packet_t pA, pB, safe; packet_t *astate, *incoming; @@ -27,9 +30,57 @@ byte d[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0 PCF8574 ioex1(0x20, 20, 21); PCF8574 ioex2(0x21, 20, 21); + PioEncoder enc1(18); // right PioEncoder enc2(14); // left +// stepper board slave config +#define MOTOR_X_ENABLE_PIN 8 +#define MOTOR_X_STEP_PIN 2 +#define MOTOR_X_DIR_PIN 5 +#define MOTOR_Y_ENABLE_PIN 8 +#define MOTOR_Y_STEP_PIN 3 +#define MOTOR_Y_DIR_PIN 6 +#define MOTOR_Z_ENABLE_PIN 8 +#define MOTOR_Z_STEP_PIN 4 +#define MOTOR_Z_DIR_PIN 7 +uint8_t i2cAddress = 0x08; // arduino address +I2Cwrapper wrapper(i2cAddress); +AccelStepperI2C stepperX(&wrapper); // Stepper Motor 1 +AccelStepperI2C stepperY(&wrapper); // Stepper Motor 2 +AccelStepperI2C stepperZ(&wrapper); // Stepper Motor 3 +bool stepperXdir = true; // true=CW, false=CCW +bool stepperYdir = true; +bool stepperZdir = true; +#define defMaxSpeed 1000000 +#define defAcceleration 1000000 +#define stepsToGo 1000 // 200 steps/rev w/o microstepping + +Sabertooth swivel[2] = { Sabertooth(128), Sabertooth(129) }; +Sabertooth actuators(130); + +#define MIN_MICROS 800 +#define MAX_MICROS 2450 + +#define SERVO_PIN_1 5 +#define SERVO_PIN_2 6 +#define SERVO_PIN_3 7 +#define SERVO_PIN_4 9 + +typedef struct +{ + int servoIndex; + uint8_t servoPin; +} ISR_servo_t; + + +#define NUM_SERVOS 4 + +ISR_servo_t ISR_servo[NUM_SERVOS] = +{ + { -1, SERVO_PIN_1 }, { -1, SERVO_PIN_2 }, { -1, SERVO_PIN_3 }, { -1, SERVO_PIN_4 } +}; + MCP3008 adc; int count = 0; int mode = 1; @@ -46,7 +97,21 @@ int acceleration = 1; bool turbo = false; int left_cooldown = 0; int right_cooldown = 0; -int olddisplay = 99999; +int olddisplay = 99999; // guarantee a change when first value comes in + +#define FLSTEER 1 +#define FRSTEER 2 +#define BLSTEER 3 +#define BRSTEER 4 +#define FLDRIVE 5 +#define FRDRIVE 6 +#define BLDRIVE 7 +#define BRDRIVE 8 +#define EXTEND1 9 +#define EXTEND2 10 +#define LIFT1 11 +#define LIFT2 12 +#define LIFT3 13 unsigned int getButton(unsigned int num) { if (num <= 7) { @@ -63,7 +128,7 @@ unsigned int getDPad() { } -void FeedbackHandler(DDLayer* pLayer, DDFeedbackType type, const DDFeedback&) { +/*void FeedbackHandler(DDLayer* pLayer, DDFeedbackType type, const DDFeedback&) { if (pLayer == optionsdisplay) { // clicked the "clear" button if(turbo) { @@ -76,7 +141,7 @@ void FeedbackHandler(DDLayer* pLayer, DDFeedbackType type, const DDFeedback&) { } //delay(100); } -} +}*/ void osmc_init() { digitalWrite(ALI1, LOW); @@ -238,29 +303,33 @@ void set_mosfet(bool pin, bool value) { void set_digit(byte digit, byte value) { - Wire.beginTransmission(0x38); + /*Wire.beginTransmission(0x38); Wire.write(0x20 + digit); Wire.write(d[value]); - Wire.endTransmission(); + Wire.endTransmission();*/ + //Serial.print("Set digit "); //Serial.print(digit); //Serial.print(" to "); //Serial.println(value); //delay(5000); + return; } void set_raw(byte digit, byte value) { - Wire.beginTransmission(0x38); + /*Wire.beginTransmission(0x38); Wire.write(0x20 + digit); Wire.write(value); - Wire.endTransmission(); + Wire.endTransmission();*/ + return; } void set_blank() { - Wire.beginTransmission(0x38); + /*Wire.beginTransmission(0x38); Wire.write(0x20); Wire.write((byte)0); Wire.write((byte)0); - Wire.endTransmission(); + Wire.endTransmission();*/ + return; } void set_hex(byte num) { byte digit1 = num; @@ -274,9 +343,8 @@ void set_hex(byte num) { } set_digit(0, digit1); set_digit(1, digit2); - if(num != olddisplay && dumbdisplay.connected() && millis() % 10 < 1) { + if(num != olddisplay && millis() % 10 < 1) { olddisplay = num; - sevenSeg->showHexNumber(num); } set_raw(4, 0x00); // clear second dot } @@ -292,13 +360,54 @@ void set_dec(byte num) { } set_digit(0, digit1); set_digit(1, digit2); - if(num != olddisplay && dumbdisplay.connected() && millis() % 10 < 1) { + if(num != olddisplay && millis() % 10 < 1) { olddisplay = num; - sevenSeg->showNumber(num); } set_raw(4, 0x02); // set second dot } +void set_motor(byte motor, int speed) { + // 1 - 4 : swivel motors on Sabertooth 1-2 + // 5 - 8 : drive motors on Talon SRX + // 9 - 10 : actuators on Sabertooth 3 + // 11 - 13 : Steppers on slave board + // speed is -127 to 127 + Serial.print("Driving motor "); + Serial.print(motor); + Serial.print(" with speed "); + Serial.println(speed); + if (motor <= 4) { + // swerve controls + swivel[(motor - 1) / 2].motor((motor - 1) % 2, speed); + } + else if (motor <= 8) { + // Talon SRX drive + // Note: can't use the built in arduino-pico Servo.h because it uses the PIO - which is already full + // Can't use PWM because that would slow the PWM frequency to 50hz, kinda need more than that + // So we use hardware interrupt timers instead + //RP2040_ISR_Servos.setPosition(ISR_servo[motor - 5].servoIndex, position); + uint16_t newspeed = map(speed, -127, 127, MIN_MICROS, MAX_MICROS); + RP2040_ISR_Servos.setPulseWidth(ISR_servo[motor - 5].servoIndex, newspeed); + } + else if (motor <= 10) { + // actuator controls + actuators.motor((motor - 9) % 2, speed); + } + // set servos + // speed needs to be a high number to be reasonable + else if (motor == 11) { + stepperX.setSpeed((float)speed); + stepperX.runSpeedState(); + } + else if (motor == 12) { + stepperY.setSpeed((float)speed); + stepperY.runSpeedState(); + } + else if (motor == 13) { + stepperY.setSpeed((float)speed); + stepperY.runSpeedState(); + } +} void setup() { WiFi.noLowPowerMode(); @@ -355,17 +464,113 @@ void setup() { Serial.println(" done"); delay(20); - Serial.print("Initializing OSMCs.."); - set_hex(0x2); - osmc_init(); + //Serial.print("Initializing OSMCs.."); + //set_hex(0x2); + //osmc_init(); + //Serial.println(" done"); + //delay(20); + ////delay(2000); + Serial.print("Initializing motor controllers.."); + digitalWrite(ALI1, LOW); + digitalWrite(BLI1, LOW); + digitalWrite(AHI1, LOW); + digitalWrite(BHI1, LOW); + digitalWrite(ALI2, LOW); + digitalWrite(BLI2, LOW); + digitalWrite(AHI2, LOW); + digitalWrite(BHI2, LOW); + + pinMode(ALI1, OUTPUT); + pinMode(AHI1, OUTPUT); + pinMode(BLI1, OUTPUT); + pinMode(BHI1, OUTPUT); + pinMode(ALI2, OUTPUT); + pinMode(AHI2, OUTPUT); + pinMode(BLI2, OUTPUT); + pinMode(BHI2, OUTPUT); + + + digitalWrite(22, LOW); // finally, enable output buffers + pinMode(22, OUTPUT); + + // enable stepper slave board + if (!wrapper.ping()) { + Serial.println("Arduino stepper driver not found!"); + while (true) {} + } + wrapper.reset(); // reset the target device + + wrapper.setI2Cdelay(20); // Set small delay for I2C bus communication + + // attach() replaces the AccelStepper constructor, so it could also be called like this: + // stepper.attach(AccelStepper::DRIVER, 5, 6); + // stepper.attach(); // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5 + stepperX.attach(AccelStepper::DRIVER, MOTOR_X_STEP_PIN, MOTOR_X_DIR_PIN); // Stepper Motor 1 - X + stepperY.attach(AccelStepper::DRIVER, MOTOR_Y_STEP_PIN, MOTOR_Y_DIR_PIN); // Stepper Motor 2 - Y + stepperZ.attach(AccelStepper::DRIVER, MOTOR_Z_STEP_PIN, MOTOR_Z_DIR_PIN); // Stepper Motor 3 - Z + + Serial.print("stepperX.myNum="); + Serial.println(stepperX.myNum); + Serial.print("stepperY.myNum="); + Serial.println(stepperY.myNum); + Serial.print("stepperZ.myNum="); + Serial.println(stepperZ.myNum); + if (stepperX.myNum < 0) { // Should not happen after a reset + Serial.println("Error: stepperX could not be allocated"); + while (true) {} + } + if (stepperY.myNum < 0) { // Should not happen after a reset + Serial.println("Error: stepperY could not be allocated"); + while (true) {} + } + if (stepperZ.myNum < 0) { // Should not happen after a reset + Serial.println("Error: stepperZ could not be allocated"); + while (true) {} + } + stepperX.setMaxSpeed(defMaxSpeed); + stepperX.setAcceleration(defAcceleration); + stepperY.setMaxSpeed(defMaxSpeed); + stepperY.setAcceleration(defAcceleration); + stepperZ.setMaxSpeed(defMaxSpeed); + stepperZ.setAcceleration(defAcceleration); + + + // Sabertooth init + Serial2.setTX(4); // pin 5 of OSMC port 2 + Serial2.begin(9600); + Sabertooth::autobaud(Serial2); + + // Talon SRX init + for (int index = 0; index < NUM_SERVOS; index++) + { + pinMode(ISR_servo[index].servoPin, OUTPUT); + digitalWrite(ISR_servo[index].servoPin, LOW); + } + + for (int index = 0; index < NUM_SERVOS; index++) + { + ISR_servo[index].servoIndex = RP2040_ISR_Servos.setupServo(ISR_servo[index].servoPin, MIN_MICROS, MAX_MICROS); + + if (ISR_servo[index].servoIndex != -1) + { + //Serial.print(F("Setup OK Servo index = ")); Serial.println(ISR_servo[index].servoIndex); + + RP2040_ISR_Servos.setPosition(ISR_servo[index].servoIndex, 0); + } + else + { + Serial.print(F("Setup Failed Servo index = ")); Serial.println(ISR_servo[index].servoIndex); + } + } + Serial.println(" done"); delay(20); - //delay(2000); - + bool ioex1p, ioex2p = false; Serial.print("Initializing I/O expanders.."); set_hex(0x3); + if(ioex1.begin()) { delay(200); Serial.print(" 1"); @@ -374,6 +579,7 @@ void setup() { delay(20); } set_hex(0x4); + if(ioex2.begin()) { delay(20); Serial.print(" 2"); @@ -381,14 +587,13 @@ void setup() { } else { delay(20); } - Serial.println(" done"); delay(20); Serial.print("Initializing encoders.."); set_hex(0x5); - enc1.begin(); - enc2.begin(); + //enc1.begin(); + //enc2.begin(); Serial.println(" done"); delay(20); @@ -450,28 +655,28 @@ void setup() { set_offset(); Serial.println("done"); - Serial.print("Checking OSMC 1.."); - set_hex(0x9); - if (get_voltage(0) > 13) { - Serial.println(" done"); - delay(20); - pass++; - } else { - Serial.println(" WARNING: OSMC 1 battery too low or OSMC not present"); - set_hex(0xF9); - delay(500); - } - set_hex(0xA); - Serial.print("Checking OSMC 2.."); - if (get_voltage(1) > 13) { - Serial.println(" done"); - delay(20); - pass++; - } else { - Serial.println(" WARNING: OSMC 2 battery too low or OSMC not present"); - set_hex(0xFA); - delay(500); - } + //Serial.print("Checking OSMC 1.."); + //set_hex(0x9); + //if (get_voltage(0) > 13) { + // Serial.println(" done"); + // delay(20); + // pass++; + //} else { + // Serial.println(" WARNING: OSMC 1 battery too low or OSMC not present"); + // set_hex(0xF9); + // delay(500); + //} + //set_hex(0xA); + //Serial.print("Checking OSMC 2.."); + //if (get_voltage(1) > 13) { + // Serial.println(" done"); + // delay(20); + // pass++; + //} else { + // Serial.println(" WARNING: OSMC 2 battery too low or OSMC not present"); + // set_hex(0xFA); + // delay(500); + //} set_hex(0xB); Serial.print("Checking I/O expander 1.."); @@ -504,7 +709,7 @@ void setup() { Serial.print("Self tests complete: "); Serial.print(pass); - Serial.println("/6 tests passed."); + Serial.println("/4 tests passed."); Serial.println("RIB is ready to go. Starting program."); set_blank(); /*dumbdisplay.recordLayerSetupCommands(); @@ -644,8 +849,8 @@ void loop() { //SerComm.println(); set_hex(avg_speed); - drive_right(right_enabled, right_power); - drive_left(left_enabled, -left_power); + //drive_right(right_enabled, right_power); + //drive_left(left_enabled, -left_power); SerComm.println(" L: " + String(left_power) + " LT: " + String(target_left_power) + " R: " + String(right_power) + " RT: " + String(target_right_power) + " MEM FREE: "+ String(rp2040.getFreeHeap())); //if(left_power != target_left_power || right_power != target_right_power) @@ -730,9 +935,42 @@ void loop1() { delay(25); loopcount++; } + //SerComm.println("update"); - left_enabled = try_enable_left(left_enabled, get_voltage(1)); - right_enabled = try_enable_right(right_enabled, get_voltage(0)); + //left_enabled = try_enable_left(left_enabled, get_voltage(1)); + //right_enabled = try_enable_right(right_enabled, get_voltage(0)); //digitalWrite(LED_BUILTIN, LOW); + + /*if (stepperX.distanceToGo() == 0) { // Give stepper something to do... + if (stepperXdir) { + Serial.println("Driving stepper"); + stepperX.moveTo(stepsToGo); + } else { + Serial.println("Driving stepper"); + stepperX.moveTo(-stepsToGo); + } + stepperX.runState(); + stepperXdir = !stepperXdir; + } + if (stepperY.distanceToGo() == 0) { // Give stepper something to do... + if (stepperYdir) + stepperY.moveTo(stepsToGo); + else + stepperY.moveTo(-stepsToGo); + stepperY.runState(); + stepperYdir = !stepperYdir; + } + + if (stepperZ.distanceToGo() == 0) { // Give stepper something to do... + if (stepperZdir) + stepperZ.moveTo(stepsToGo); + else + stepperZ.moveTo(-stepsToGo); + stepperZ.runState(); + stepperZdir = !stepperZdir; + }*/ + for (int x = 1; x < 14; x++) { + set_motor(x, loopcount * 5); + } delay(25); } \ No newline at end of file