11#include < Arduino.h>
22#include < ODriveMCPCAN.hpp>
33
4- #define DEBUG 1
4+ // #define DEBUG 1
55#define DEBUG_GInputs 0
66
77const uint32_t SPEED_SEND_INTERVAL = 10 ;
88
9- const float_t EXTRUSION_SPD_RPS_MIN = 0 .0 ;
9+ const float_t EXTRUSION_SPD_RPS_MIN = - 30 .0 ;
1010const float_t EXTRUSION_SPD_RPS_MAX = 30.0 ;
1111
12- const pin_size_t DI_ROBOT_BWD_PIN = CONTROLLINO_MICRO_AI1 ;
1312const pin_size_t DI_ROBOT_SPD0_PIN = CONTROLLINO_MICRO_AI2 ;
1413const pin_size_t DI_ROBOT_SPD1_PIN = CONTROLLINO_MICRO_AI3 ;
1514const pin_size_t DI_ROBOT_SPD2_PIN = CONTROLLINO_MICRO_AI4 ;
@@ -19,6 +18,27 @@ const pin_size_t DI_ROBOT_SPD5_PIN = CONTROLLINO_MICRO_DI1;
1918const pin_size_t DI_ROBOT_SPD6_PIN = CONTROLLINO_MICRO_DI2 ;
2019const pin_size_t DI_ROBOT_SPD7_PIN = CONTROLLINO_MICRO_DI3 ;
2120
21+ const uint8_t NUM_SPD_BITS = 8 ;
22+
23+ pin_size_t ROBOT_SPD_PINS [] = {
24+ DI_ROBOT_SPD0_PIN ,
25+ DI_ROBOT_SPD1_PIN ,
26+ DI_ROBOT_SPD2_PIN ,
27+ DI_ROBOT_SPD3_PIN ,
28+ DI_ROBOT_SPD4_PIN ,
29+ DI_ROBOT_SPD5_PIN ,
30+ DI_ROBOT_SPD6_PIN ,
31+ DI_ROBOT_SPD7_PIN ,
32+ };
33+
34+
35+ // this is default on the controllino but I'm setting it just to be sure
36+ const uint8_t AI_RESOLUTION = 23 ;
37+
38+ // Calculate threshold value for 7V in a 0-24V range with 23-bit resolution
39+ // 7V comes from spec from ABB, I think
40+ const uint32_t AI_DIGITAL_THRESHOLD = (7.0 / 24.0 ) * ((1UL << AI_RESOLUTION ) - 1 );
41+
2242// CAN bus baudrate. Make sure this matches for every device on the bus
2343const uint32_t CAN_BAUDRATE = 125000 ;
2444
@@ -28,10 +48,11 @@ const uint32_t ODRV0_NODE_ID = 0;
2848// vendored/modified from controllino_rp2\hardware\rp2040
2949MCP2515Class& g_can_intf = CAN ;
3050
31-
3251void printAndHalt (const char * message) {
52+ #ifdef DEBUG
3353 Serial.println (message);
34- while (true ); // Infinite loop
54+ #endif
55+ while (true );
3556}
3657
3758// Instantiate ODrive objects
@@ -92,52 +113,60 @@ bool setupCan() {
92113}
93114
94115void setup () {
116+ #ifdef DEBUG
95117 Serial.begin (115200 );
96- // wait since Controllino Micro uses software USB not hardware USB-to-serial
118+
119+ // wait since Controllino Micro uses software USB not hardware USB-to-serial */
97120 while (!Serial);
98121 Serial.println (" Starting..." );
122+ #endif
99123
100- // setup robot input pins
101- pinMode (DI_ROBOT_BWD_PIN , INPUT );
102- pinMode (DI_ROBOT_SPD0_PIN , INPUT );
103- pinMode (DI_ROBOT_SPD1_PIN , INPUT );
104- pinMode (DI_ROBOT_SPD2_PIN , INPUT );
105- pinMode (DI_ROBOT_SPD3_PIN , INPUT );
106- pinMode (DI_ROBOT_SPD4_PIN , INPUT );
107- pinMode (DI_ROBOT_SPD5_PIN , INPUT );
108- pinMode (DI_ROBOT_SPD6_PIN , INPUT );
109- pinMode (DI_ROBOT_SPD7_PIN , INPUT );
124+ delay (200 );
125+
126+ analogReadResolution (AI_RESOLUTION );
127+
128+ // setup robot spd input pins
129+ for (pin_size_t pin : ROBOT_SPD_PINS ) {
130+ setDigitalThreshold (pin, AI_DIGITAL_THRESHOLD ); // noop for digital inputs
131+ pinMode (pin, INPUT );
132+ }
110133
111134 // Register callbacks for the heartbeat and encoder feedback messages
112135 g_odrv0.onFeedback (onFeedback, &g_odrv0_user_data);
113136 g_odrv0.onStatus (onHeartbeat, &g_odrv0_user_data);
114137
115- if (!setupCan ()) {
116- printAndHalt (" CAN failed to initialize: reset required" );
117- }
138+ if (!setupCan ()) printAndHalt (" CAN failed to initialize: reset required" );
118139
140+ #ifdef DEBUG
119141 Serial.println (" Waiting for ODrive..." );
142+ #endif
120143 while (!g_odrv0_user_data.received_heartbeat ) {
121144 pumpEvents (g_can_intf);
122145 delay (100 );
123146 }
124147
148+ #ifdef DEBUG
125149 Serial.println (" found ODrive" );
126150
127151 // request bus voltage and current (1sec timeout)
128152 Serial.println (" attempting to read bus voltage and current" );
153+ #endif
154+
129155 Get_Bus_Voltage_Current_msg_t vbus;
130156
131- if (!g_odrv0.request (vbus, 1 )) {
157+ if (!g_odrv0.getBusVI (vbus, 1000 )) {
132158 printAndHalt (" vbus request failed!" );
133159 }
134160
161+ #ifdef DEBUG
135162 Serial.print (" DC voltage [V]: " );
136163 Serial.println (vbus.Bus_Voltage );
137164 Serial.print (" DC current [A]: " );
138165 Serial.println (vbus.Bus_Current );
139166
140167 Serial.println (" Enabling closed loop control..." );
168+ #endif
169+
141170 while (g_odrv0_user_data.last_heartbeat .Axis_State != ODriveAxisState::AXIS_STATE_CLOSED_LOOP_CONTROL ) {
142171 g_odrv0.clearErrors ();
143172 delay (1 );
@@ -155,7 +184,9 @@ void setup() {
155184 pumpEvents (g_can_intf);
156185 }
157186 }
187+ #ifdef DEBUG
158188 Serial.println (" ODrive running!" );
189+ #endif
159190}
160191
161192#if DEBUG_GInputs == 1
@@ -174,9 +205,20 @@ uint8_t readSpdInputs() {
174205}
175206#else
176207uint8_t readSpdInputs () {
177- return (digitalRead (DI_ROBOT_SPD0_PIN ) << 0 ) | (digitalRead (DI_ROBOT_SPD1_PIN ) << 1 ) | (digitalRead (DI_ROBOT_SPD2_PIN ) << 2 ) | (digitalRead (DI_ROBOT_SPD3_PIN ) << 3 ) | (digitalRead (DI_ROBOT_SPD4_PIN ) << 4 ) | (digitalRead (DI_ROBOT_SPD5_PIN ) << 5 ) | (digitalRead (DI_ROBOT_SPD6_PIN ) << 6 ) | (digitalRead (DI_ROBOT_SPD7_PIN ) << 7 );
208+ uint8_t rawValue = 0 ;
209+
210+ for (int i = 0 ; i < NUM_SPD_BITS ; i++) {
211+ rawValue |= (digitalRead (ROBOT_SPD_PINS [i]) << i);
212+ }
213+ return rawValue;
214+ }
215+ #endif
216+
217+ int8_t readSignedSpdInputs () {
218+ // Convert to signed int8_t
219+ // Values 128-255 will become -128 to -1
220+ return (int8_t )readSpdInputs ();
178221}
179- #endif // DEBUG_GInputs
180222
181223uint32_t g_prev_millis = 0 ;
182224uint32_t g_cur_millis = 0 ;
@@ -190,28 +232,27 @@ void loop() {
190232 if (g_cur_millis - g_prev_millis >= SPEED_SEND_INTERVAL ) {
191233 g_prev_millis = g_cur_millis;
192234
193- g_spd_reading = readSpdInputs ();
235+ g_spd_reading = readSignedSpdInputs ();
194236
195- #if DEBUG == 1
196- Serial.print (" g_spdReading:" );
197- Serial.print (g_spd_reading);
198- #endif // DEBUG
199237
200- if (g_spd_reading < 1 ) {
201- g_odrv0.setVelocity (0 );
202- } else {
203- g_odrv0.setVelocity (map (g_spd_reading, 1 , 255 , EXTRUSION_SPD_RPS_MIN , EXTRUSION_SPD_RPS_MAX ));
204- }
238+ g_odrv0.setVelocity (map (g_spd_reading,
239+ -127 ,
240+ 127 ,
241+ EXTRUSION_SPD_RPS_MIN , EXTRUSION_SPD_RPS_MAX ));
205242
206- #if DEBUG == 1
207- // print position and velocity for Serial Plotter
243+ #ifdef DEBUG
244+ Serial.print (" g_spdReading:" );
245+ Serial.print (g_spd_reading);
246+ Serial.print (" ," );
247+ Serial.print (" g_odrv0-vel:" );
208248 if (g_odrv0_user_data.received_feedback ) {
209249 Get_Encoder_Estimates_msg_t feedback = g_odrv0_user_data.last_feedback ;
210250 g_odrv0_user_data.received_feedback = false ;
211- Serial.print (" ," );
212- Serial.print (" g_odrv0-vel:" );
251+
213252 Serial.println (feedback.Vel_Estimate );
253+ } else {
254+ Serial.println (" ERROR" );
214255 }
215- #endif // DEBUG
256+ #endif
216257 }
217258}
0 commit comments