diff options
| author | Abel Tim <abel@main.home> | 2024-07-15 14:53:41 +0200 |
|---|---|---|
| committer | Abel Tim <abel@main.home> | 2024-07-15 14:53:41 +0200 |
| commit | 6fcefaf1c7087675d403bc3451ca1997ecaa83d6 (patch) | |
| tree | e43f6e74fac54aa3c90a514508fe2415430990c3 | |
| parent | 3ce2797f62a124a54644968141feab710b816837 (diff) | |
| download | robotica-6fcefaf1c7087675d403bc3451ca1997ecaa83d6.tar.gz robotica-6fcefaf1c7087675d403bc3451ca1997ecaa83d6.zip | |
poster
| -rw-r--r-- | debug/Scanner/Scanner.ino | 194 | ||||
| -rw-r--r-- | debug/motordriver/PID/PID.ino | 36 | ||||
| -rw-r--r-- | debug/motordriver/PID_autotune/PID.py | 131 | ||||
| -rw-r--r-- | debug/motordriver/PID_autotune/PID_autotune.ino | 82 | ||||
| -rw-r--r-- | debug/motordriver/PID_autotune/man_test.py | 16 | ||||
| -rw-r--r-- | poster.png | bin | 0 -> 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 Binary files differnew file mode 100644 index 0000000..79d4055 --- /dev/null +++ b/poster.png |
