summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbel Tim <abel@main.home>2024-07-15 14:53:41 +0200
committerAbel Tim <abel@main.home>2024-07-15 14:53:41 +0200
commit6fcefaf1c7087675d403bc3451ca1997ecaa83d6 (patch)
treee43f6e74fac54aa3c90a514508fe2415430990c3
parent3ce2797f62a124a54644968141feab710b816837 (diff)
downloadrobotica-6fcefaf1c7087675d403bc3451ca1997ecaa83d6.tar.gz
robotica-6fcefaf1c7087675d403bc3451ca1997ecaa83d6.zip
poster
-rw-r--r--debug/Scanner/Scanner.ino194
-rw-r--r--debug/motordriver/PID/PID.ino36
-rw-r--r--debug/motordriver/PID_autotune/PID.py131
-rw-r--r--debug/motordriver/PID_autotune/PID_autotune.ino82
-rw-r--r--debug/motordriver/PID_autotune/man_test.py16
-rw-r--r--poster.pngbin0 -> 683947 bytes
6 files changed, 439 insertions, 20 deletions
diff --git a/debug/Scanner/Scanner.ino b/debug/Scanner/Scanner.ino
new file mode 100644
index 0000000..879dbd6
--- /dev/null
+++ b/debug/Scanner/Scanner.ino
@@ -0,0 +1,194 @@
+// Wire Scanner - scans for I2C devices on all Wire ports
+//
+// This Wire library adapted is for Teensy boards
+//
+// https://github.com/PaulStoffregen/Wire/
+//
+// Adapted from I2C Scanner originally published on Arduino Playground
+// see comments below for link and credits for original authors.
+
+#include <Wire.h>
+
+void setup() {
+#if WIRE_INTERFACES_COUNT >= 1
+ //Wire.setSCL(16); // uncomment these to use alternate Wire pins
+ //Wire.setSDA(17);
+ Wire.begin();
+#endif
+ Serial.begin(9600);
+ while (!Serial); // Wait for Arduino Serial Monitor
+ Serial.println(F("\nI2C Scanner"));
+}
+
+
+void loop() {
+ Serial.println();
+#if WIRE_INTERFACES_COUNT >= 1
+ Serial.println(F("Scanning Wire..."));
+ scan(Wire);
+ delay(500);
+#endif
+ delay(2000); // wait 5 seconds for next scan
+}
+
+
+void scan(TwoWire &myport) {
+ int nDevices = 0;
+ for (int address = 1; address < 127; address++) {
+ // The i2c_scanner uses the return value of
+ // the Write.endTransmisstion to see if
+ // a device did acknowledge to the address.
+ myport.beginTransmission(address);
+ int error = myport.endTransmission();
+
+ if (error == 0) {
+ Serial.print(F("Device found at address 0x"));
+ if (address < 16) {
+ Serial.print("0");
+ }
+ Serial.print(address,HEX);
+ Serial.print(" (");
+ printKnownChips(address);
+ Serial.println(")");
+ nDevices++;
+ } else if (error==4) {
+ Serial.print(F("Unknown error at address 0x"));
+ if (address < 16) {
+ Serial.print("0");
+ }
+ Serial.println(address,HEX);
+ }
+ }
+ if (nDevices == 0) {
+ Serial.println(F("No I2C devices found"));
+ } else {
+ Serial.println(F("done"));
+ }
+ Serial.println();
+}
+
+
+void printKnownChips(byte address)
+{
+ // Is this list missing part numbers for chips you use?
+ // Please suggest additions here:
+ // https://github.com/PaulStoffregen/Wire/issues/new
+ switch (address) {
+ case 0x00: Serial.print(F("AS3935")); break;
+ case 0x01: Serial.print(F("AS3935")); break;
+ case 0x02: Serial.print(F("AS3935")); break;
+ case 0x03: Serial.print(F("AS3935")); break;
+ case 0x04: Serial.print(F("ADAU1966")); break;
+ case 0x0A: Serial.print(F("SGTL5000")); break; // MCLK required
+ case 0x0B: Serial.print(F("SMBusBattery?")); break;
+ case 0x0C: Serial.print(F("AK8963")); break;
+ case 0x10: Serial.print(F("CS4272")); break;
+ case 0x11: Serial.print(F("Si4713")); break;
+ case 0x13: Serial.print(F("VCNL4000,AK4558")); break;
+ case 0x18: Serial.print(F("LIS331DLH")); break;
+ case 0x19: Serial.print(F("LSM303,LIS331DLH")); break;
+ case 0x1A: Serial.print(F("WM8731")); break;
+ case 0x1C: Serial.print(F("LIS3MDL")); break;
+ case 0x1D: Serial.print(F("LSM303D,LSM9DS0,ADXL345,MMA7455L,LSM9DS1,LIS3DSH")); break;
+ case 0x1E: Serial.print(F("LSM303D,HMC5883L,FXOS8700,LIS3DSH")); break;
+ case 0x20: Serial.print(F("MCP23017,MCP23008,PCF8574,FXAS21002,SoilMoisture")); break;
+ case 0x21: Serial.print(F("MCP23017,MCP23008,PCF8574")); break;
+ case 0x22: Serial.print(F("MCP23017,MCP23008,PCF8574")); break;
+ case 0x23: Serial.print(F("MCP23017,MCP23008,PCF8574")); break;
+ case 0x24: Serial.print(F("MCP23017,MCP23008,PCF8574,ADAU1966,HM01B0")); break;
+ case 0x25: Serial.print(F("MCP23017,MCP23008,PCF8574")); break;
+ case 0x26: Serial.print(F("MCP23017,MCP23008,PCF8574")); break;
+ case 0x27: Serial.print(F("MCP23017,MCP23008,PCF8574,LCD16x2,DigoleDisplay")); break;
+ case 0x28: Serial.print(F("BNO055,EM7180,CAP1188")); break;
+ case 0x29: Serial.print(F("TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188")); break;
+ case 0x2A: Serial.print(F("SGTL5000,CAP1188")); break;
+ case 0x2B: Serial.print(F("CAP1188")); break;
+ case 0x2C: Serial.print(F("MCP44XX ePot")); break;
+ case 0x2D: Serial.print(F("MCP44XX ePot")); break;
+ case 0x2E: Serial.print(F("MCP44XX ePot")); break;
+ case 0x2F: Serial.print(F("MCP44XX ePot")); break;
+ case 0x30: Serial.print(F("Si7210")); break;
+ case 0x31: Serial.print(F("Si7210")); break;
+ case 0x32: Serial.print(F("Si7210")); break;
+ case 0x33: Serial.print(F("MAX11614,MAX11615,Si7210,MLX90640,MLX90641")); break;
+ case 0x34: Serial.print(F("MAX11612,MAX11613")); break;
+ case 0x35: Serial.print(F("MAX11616,MAX11617")); break;
+ case 0x38: Serial.print(F("RA8875,FT6206,MAX98390")); break;
+ case 0x39: Serial.print(F("TSL2561, APDS9960")); break;
+ case 0x3A: Serial.print(F("MLX90632")); break;
+ case 0x3C: Serial.print(F("SSD1306,DigisparkOLED")); break;
+ case 0x3D: Serial.print(F("SSD1306")); break;
+ case 0x40: Serial.print(F("PCA9685,Si7021,MS8607")); break;
+ case 0x41: Serial.print(F("STMPE610,PCA9685")); break;
+ case 0x42: Serial.print(F("PCA9685")); break;
+ case 0x43: Serial.print(F("PCA9685")); break;
+ case 0x44: Serial.print(F("PCA9685, SHT3X, ADAU1966")); break;
+ case 0x45: Serial.print(F("PCA9685, SHT3X")); break;
+ case 0x46: Serial.print(F("PCA9685")); break;
+ case 0x47: Serial.print(F("PCA9685")); break;
+ case 0x48: Serial.print(F("ADS1115,PN532,TMP102,LM75,PCF8591,CS42448")); break;
+ case 0x49: Serial.print(F("ADS1115,TSL2561,PCF8591,CS42448,TC74A1")); break;
+ case 0x4A: Serial.print(F("ADS1115,Qwiic Keypad,CS42448")); break;
+ case 0x4B: Serial.print(F("ADS1115,TMP102,BNO080,Qwiic Keypad,CS42448")); break;
+ case 0x50: Serial.print(F("EEPROM,FRAM")); break;
+ case 0x51: Serial.print(F("EEPROM")); break;
+ case 0x52: Serial.print(F("Nunchuk,EEPROM")); break;
+ case 0x53: Serial.print(F("ADXL345,EEPROM")); break;
+ case 0x54: Serial.print(F("EEPROM")); break;
+ case 0x55: Serial.print(F("EEPROM")); break;
+ case 0x56: Serial.print(F("EEPROM")); break;
+ case 0x57: Serial.print(F("EEPROM")); break;
+ case 0x58: Serial.print(F("TPA2016,MAX21100")); break;
+ case 0x5A: Serial.print(F("MPR121,MLX90614")); break;
+ case 0x60: Serial.print(F("MPL3115,MCP4725,MCP4728,TEA5767,Si5351")); break;
+ case 0x61: Serial.print(F("MCP4725,AtlasEzoDO")); break;
+ case 0x62: Serial.print(F("LidarLite,MCP4725,AtlasEzoORP")); break;
+ case 0x63: Serial.print(F("MCP4725,AtlasEzoPH")); break;
+ case 0x64: Serial.print(F("AtlasEzoEC, ADAU1966")); break;
+ case 0x66: Serial.print(F("AtlasEzoRTD")); break;
+ case 0x68: Serial.print(F("DS1307,DS3231,MPU6050,MPU9050,MPU9250,ITG3200,ITG3701,LSM9DS0,L3G4200D")); break;
+ case 0x69: Serial.print(F("MPU6050,MPU9050,MPU9250,ITG3701,L3G4200D")); break;
+ case 0x6A: Serial.print(F("LSM9DS1")); break;
+ case 0x6B: Serial.print(F("LSM9DS0")); break;
+ case 0x6F: Serial.print(F("Qwiic Button")); break;
+ case 0x70: Serial.print(F("HT16K33,TCA9548A")); break;
+ case 0x71: Serial.print(F("SFE7SEG,HT16K33")); break;
+ case 0x72: Serial.print(F("HT16K33")); break;
+ case 0x73: Serial.print(F("HT16K33")); break;
+ case 0x76: Serial.print(F("MS5607,MS5611,MS5637,BMP280")); break;
+ case 0x77: Serial.print(F("BMP085,BMA180,BMP280,MS5611")); break;
+ case 0x7C: Serial.print(F("FRAM_ID")); break;
+ default: Serial.print(F("unknown chip"));
+ }
+}
+
+
+// --------------------------------------
+// i2c_scanner
+// https://playground.arduino.cc/Main/I2cScanner/
+//
+// Version 1
+// This program (or code that looks like it)
+// can be found in many places.
+// For example on the Arduino.cc forum.
+// The original author is not know.
+// Version 2, Juni 2012, Using Arduino 1.0.1
+// Adapted to be as simple as possible by Arduino.cc user Krodal
+// Version 3, Feb 26 2013
+// V3 by louarnold
+// Version 4, March 3, 2013, Using Arduino 1.0.3
+// by Arduino.cc user Krodal.
+// Changes by louarnold removed.
+// Scanning addresses changed from 0...127 to 1...119,
+// according to the i2c scanner by Nick Gammon
+// http://www.gammon.com.au/forum/?id=10896
+// Version 5, March 28, 2013
+// As version 4, but address scans now to 127.
+// A sensor seems to use address 120.
+// Version 6, November 27, 2015.
+// Added waiting for the Leonardo serial communication.
+//
+//
+// This sketch tests the standard 7-bit addresses
+// Devices with higher bit address might not be seen properly.
+//
diff --git a/debug/motordriver/PID/PID.ino b/debug/motordriver/PID/PID.ino
index 313b440..c7f351a 100644
--- a/debug/motordriver/PID/PID.ino
+++ b/debug/motordriver/PID/PID.ino
@@ -1,14 +1,15 @@
#include <TimerThree.h>
-#include "ArduPID.h"
+#include <QuickPID.h>
-ArduPID myController;
-double input;
-double output;
-double setpoint = 950; // Desired RPM
-double p = 40; // PID P-term
-double i = 2; // PID I-term
-double d = 0; // PID D-term
+//https://www.pololu.com/product/2997
+//https://www.pololu.com/product/4861
+
+
+float Setpoint, Input, Output;
+float Kp = 2, Ki = 5, Kd = 1;
+QuickPID myPID(&Input, &Output, &Setpoint);
+
int enA = 1; // PWM pin
int enB = 2; // GND
@@ -44,12 +45,10 @@ void setup() {
Serial.begin(9600);
// PID settings
- myController.begin(&input, &output, &setpoint, p, i, d);
- myController.setOutputLimits(0, 1000); // Output limits for PWM control
- myController.setBias(500); // Starting bias for PWM
- myController.setWindUpLimits(-50, 50);
-
- myController.start();
+ Input = rpm;
+ Setpoint = 500;
+ myPID.SetTunings(Kp, Ki, Kd);
+ myPID.SetMode(myPID.Control::automatic);
}
void updatePWM() {
@@ -106,11 +105,8 @@ void move(int sped) {
}
void loop() {
- readenc();
- input = rpm;
- myController.compute();
- myController.debug(&Serial, "myController", PRINT_INPUT);
+ Input = rpm;
+ myPID.Compute();
+ move(Output);
- move(output); // Replace with plant control signal
- delay(100);
}
diff --git a/debug/motordriver/PID_autotune/PID.py b/debug/motordriver/PID_autotune/PID.py
new file mode 100644
index 0000000..e24dbd6
--- /dev/null
+++ b/debug/motordriver/PID_autotune/PID.py
@@ -0,0 +1,131 @@
+import serial
+import time
+from simple_pid import PID
+import matplotlib.pyplot as plt
+from matplotlib.widgets import Slider, Button
+
+# Initialize serial communication
+arduino = serial.Serial(port='/dev/ttyACM0', baudrate=115200, timeout=.1)
+
+# Function to write to and read from Arduino
+def write_read(x):
+ arduino.write(bytes(x, 'utf-8'))
+ time.sleep(0.05)
+ data = arduino.readline().decode().strip()
+ return data
+
+# Real-time plotting setup
+fig, (ax1, ax2) = plt.subplots(2, 1)
+feedback_list = []
+control_list = []
+setpoint_list = []
+
+def clamp(feedback, min_value, max_value):
+ return max(min(feedback, max_value), min_value)
+
+def update_plot(feedback, control, setpoint):
+ feedback_clamped = clamp(feedback, 0, 1000) # Clamp feedback value between 0 and 1000
+ feedback_list.append(feedback_clamped)
+ control_list.append(control)
+ setpoint_list.append(setpoint)
+
+ # Limit lists to 50 items for smoother plotting
+ if len(feedback_list) > 50:
+ feedback_list.pop(0)
+ control_list.pop(0)
+ setpoint_list.pop(0)
+
+ ax1.clear()
+ ax2.clear()
+
+ ax1.plot(feedback_list, label="Feedback")
+ ax1.plot(setpoint_list, label="Setpoint")
+ ax1.legend()
+
+ ax2.plot(control_list, label="Control")
+ ax2.legend()
+
+ ax1.set_ylabel('RPM')
+ ax2.set_ylabel('Control Signal')
+ ax2.set_xlabel('Time')
+
+ plt.tight_layout()
+ plt.pause(0.05) # Pause to allow plot to update
+
+# Initialize PID controller with output limits
+initial_setpoint = 500 # Initial setpoint
+pid = PID(0, 0, 0, output_limits=(0, 1000))
+pid.setpoint = initial_setpoint
+
+# Initialize PID parameters (preserved across resets)
+preserved_parameters = {
+ 'Kp': 0,
+ 'Ki': 0,
+ 'Kd': 0,
+ 'setpoint': initial_setpoint
+}
+
+# Function to update PID parameters
+def update_pid(val):
+ pid.Kp = s_kp.val
+ pid.Ki = s_ki.val
+ pid.Kd = s_kd.val
+ preserved_parameters['Kp'] = s_kp.val
+ preserved_parameters['Ki'] = s_ki.val
+ preserved_parameters['Kd'] = s_kd.val
+ setpoint = s_setpoint.val
+ pid.setpoint = setpoint
+ preserved_parameters['setpoint'] = setpoint
+ print(f"Setpoint: {setpoint}, Kp: {pid.Kp}, Ki: {pid.Ki}, Kd: {pid.Kd}")
+
+# Create sliders for PID parameters and setpoint
+axcolor = 'lightgoldenrodyellow'
+ax_setpoint = plt.axes([0.15, 0.1, 0.65, 0.03], facecolor=axcolor)
+ax_kp = plt.axes([0.15, 0.15, 0.65, 0.03], facecolor=axcolor)
+ax_ki = plt.axes([0.15, 0.2, 0.65, 0.03], facecolor=axcolor)
+ax_kd = plt.axes([0.15, 0.25, 0.65, 0.03], facecolor=axcolor)
+
+s_setpoint = Slider(ax_setpoint, 'Setpoint', 0, 1000, valinit=initial_setpoint)
+s_kp = Slider(ax_kp, 'Kp', 0, 10, valinit=preserved_parameters['Kp'])
+s_ki = Slider(ax_ki, 'Ki', 0, 10, valinit=preserved_parameters['Ki'])
+s_kd = Slider(ax_kd, 'Kd', 0, 10, valinit=preserved_parameters['Kd'])
+
+s_setpoint.on_changed(update_pid)
+s_kp.on_changed(update_pid)
+s_ki.on_changed(update_pid)
+s_kd.on_changed(update_pid)
+
+# Function to reset algorithm and set speed to zero
+def reset_algorithm(event):
+ global feedback_list, control_list, setpoint_list
+ feedback_list.clear()
+ control_list.clear()
+ setpoint_list.clear()
+ pid.reset()
+ s_setpoint.set_val(preserved_parameters['setpoint'])
+ s_kp.set_val(preserved_parameters['Kp'])
+ s_ki.set_val(preserved_parameters['Ki'])
+ s_kd.set_val(preserved_parameters['Kd'])
+ print("Algorithm reset")
+ time.sleep(1) # Delay of 1 second after reset
+
+# Create reset button
+ax_reset = plt.axes([0.8, 0.02, 0.1, 0.05])
+btn_reset = Button(ax_reset, 'Reset')
+btn_reset.on_clicked(reset_algorithm)
+
+# Function to update Arduino with clamped control signal
+def update_arduino_control(control):
+ control_clamped = clamp(control, 0, 1000)
+ write_read(str(control_clamped))
+
+# Control loop
+while True:
+ feedback = float(write_read(str(pid.setpoint)))
+ feedback_clamped = clamp(feedback, 0, 1000) # Clamp feedback value between 0 and 1000
+ control = pid(feedback_clamped)
+ update_arduino_control(control)
+ update_plot(feedback_clamped, control, pid.setpoint)
+
+# Keep plot open
+plt.show()
diff --git a/debug/motordriver/PID_autotune/PID_autotune.ino b/debug/motordriver/PID_autotune/PID_autotune.ino
new file mode 100644
index 0000000..ab99c50
--- /dev/null
+++ b/debug/motordriver/PID_autotune/PID_autotune.ino
@@ -0,0 +1,82 @@
+int enA = 1;
+int enB = 2;
+int pwm1 = 3;
+int pwm2 = 4;
+int encoA = 5;
+int encoB = 6;
+
+int speed = 1; // speed 0-1000
+
+double sp = 0.00;
+double rpm = 0.00;
+volatile long encount = 0;
+unsigned long Ltime = 0;
+unsigned long Ctime = 0;
+unsigned long Ptime = 0;
+
+int mess;
+
+void setup() {
+ pinMode(enA, OUTPUT);
+ pinMode(enB, OUTPUT);
+ pinMode(pwm1, OUTPUT);
+ pinMode(pwm2, OUTPUT);
+
+ pinMode(encoA, INPUT_PULLUP);
+ pinMode(encoB, INPUT_PULLUP);
+
+ attachInterrupt(digitalPinToInterrupt(encoA), encoderISR, CHANGE);
+ attachInterrupt(digitalPinToInterrupt(encoB), encoderISR, CHANGE);
+
+ Serial.begin(115200);
+ Serial.setTimeout(1);
+}
+
+void encoderISR() {
+ encount++;
+}
+
+void readenc() {
+ Ctime = micros();
+ Ptime = Ctime - Ltime;
+ Ltime = Ctime;
+ rpm = (encount / 211.2) * (60000000.0 / Ptime);
+ /*Serial.print("RPM: ");
+ Serial.print(rpm);
+ Serial.print(" Sample period:");
+ Serial.print(Ptime);
+ Serial.print("ms, encoder count:");
+ Serial.println(encount);
+ */
+
+ encount = 0;
+}
+void resetenc(){
+ Ctime = micros();
+ Ltime = Ctime;
+ encount = 0;
+}
+
+void move(int sped) {
+ sp = abs(sped)*2.55;
+ analogWrite(enA, sp);
+ digitalWrite(enB, LOW);
+ if (sped < 0) {
+ //Serial.print("back ");
+ digitalWrite(pwm1, LOW);
+ digitalWrite(pwm2, HIGH);
+ } else {
+ //Serial.print("forward ");
+ digitalWrite(pwm1, HIGH);
+ digitalWrite(pwm2, LOW);
+ }
+ //Serial.println(sp);
+}
+
+void loop() {
+ while (!Serial.available());
+ mess = Serial.readString().toInt();
+ move(mess);
+ readenc();
+ Serial.print(rpm);
+}
diff --git a/debug/motordriver/PID_autotune/man_test.py b/debug/motordriver/PID_autotune/man_test.py
new file mode 100644
index 0000000..52c84e3
--- /dev/null
+++ b/debug/motordriver/PID_autotune/man_test.py
@@ -0,0 +1,16 @@
+import serial
+import time
+
+arduino = serial.Serial(port='/dev/ttyACM0', baudrate=115200, timeout=.1)
+
+def write_read(x):
+ arduino.write(bytes(x, 'utf-8'))
+ time.sleep(0.05)
+ data = arduino.readline()
+ return data
+
+while True:
+ num = input("Enter a number: ") # Taking input from user
+ value = write_read(num)
+ print(value) # printing the value
+
diff --git a/poster.png b/poster.png
new file mode 100644
index 0000000..79d4055
--- /dev/null
+++ b/poster.png
Binary files differ