parent
8d12edb538
commit
7d0ccb366d
@ -1,203 +1,203 @@
|
|||||||
#include <digitalWriteFast.h>
|
#include <digitalWriteFast.h>
|
||||||
//this is to use DWF library, it will increase the speed of digitalRead/Write command
|
//this is to use DWF library, it will increase the speed of digitalRead/Write command
|
||||||
//used in the interrupt function doEncoderMotor0, but may be used everywhere.
|
//used in the interrupt function doEncoderMotor0, but may be used everywhere.
|
||||||
/*
|
/*
|
||||||
https://github.com/danithebest91/ServoStrap
|
https://github.com/danithebest91/ServoStrap
|
||||||
i have made this code for the LMD18245 motor controller,
|
i have made this code for the LMD18245 motor controller,
|
||||||
i have merged the pid code of Josh Kopel
|
i have merged the pid code of Josh Kopel
|
||||||
whith the code of makerbot servo-controller board,
|
whith the code of makerbot servo-controller board,
|
||||||
you can use this code on the some board changing some values.
|
you can use this code on the some board changing some values.
|
||||||
Daniele Poddighe
|
Daniele Poddighe
|
||||||
external ardware require a quadrature encoder, timing slit strip and a dc motor,
|
external ardware require a quadrature encoder, timing slit strip and a dc motor,
|
||||||
all you can find inside an old printer, i have took it from canon and hp printers(psc1510)
|
all you can find inside an old printer, i have took it from canon and hp printers(psc1510)
|
||||||
|
|
||||||
for motor controll you can choose different type of H-bridge, i have used LMD18245,
|
for motor controll you can choose different type of H-bridge, i have used LMD18245,
|
||||||
you can order 3 of it on ti.com sample request, the hardware needed is explained on the datasheet but i'm drowing
|
you can order 3 of it on ti.com sample request, the hardware needed is explained on the datasheet but i'm drowing
|
||||||
the schematic and PCB layout on eagle.
|
the schematic and PCB layout on eagle.
|
||||||
|
|
||||||
|
|
||||||
read a rotary encoder with interrupts
|
read a rotary encoder with interrupts
|
||||||
Encoder hooked up with common to GROUND,
|
Encoder hooked up with common to GROUND,
|
||||||
encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
|
encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
|
||||||
it doesn't matter which encoder pin you use for A or B
|
it doesn't matter which encoder pin you use for A or B
|
||||||
|
|
||||||
is possible to change PID costants by sending on serial interfaces the values separated by ',' in this order: KP,KD,KI
|
is possible to change PID costants by sending on serial interfaces the values separated by ',' in this order: KP,KD,KI
|
||||||
example: 5.2,3.1,0 so we have KP=5.2 KD=3.1 KI=0 is only for testing purposes, but i will leave this function with eeprom storage
|
example: 5.2,3.1,0 so we have KP=5.2 KD=3.1 KI=0 is only for testing purposes, but i will leave this function with eeprom storage
|
||||||
|
|
||||||
This code use Port manipulation :
|
This code use Port manipulation :
|
||||||
Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino board
|
Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino board
|
||||||
(the ATmega8 and ATmega168) have three ports:
|
(the ATmega8 and ATmega168) have three ports:
|
||||||
B (digital pin 8 to 13)
|
B (digital pin 8 to 13)
|
||||||
C (analog input pins)
|
C (analog input pins)
|
||||||
D (digital pins 0 to 7)
|
D (digital pins 0 to 7)
|
||||||
https://www.arduino.cc/en/Reference/PortManipulation
|
https://www.arduino.cc/en/Reference/PortManipulation
|
||||||
|
|
||||||
https://www.arduino.cc/en/Hacking/PinMapping
|
https://www.arduino.cc/en/Hacking/PinMapping
|
||||||
https://www.arduino.cc/en/Hacking/PinMapping168
|
https://www.arduino.cc/en/Hacking/PinMapping168
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define encoder0PinA 2 // PD2 (INT0) You can't modify port mapping here because this code use Port manipulation (I2)
|
#define encoder0PinA 2 // PD2 (INT0) You can't modify port mapping here because this code use Port manipulation (I2)
|
||||||
#define encoder0PinB 8 // PB0; (I8)
|
#define encoder0PinB 8 // PB0; (I8)
|
||||||
|
|
||||||
#define SpeedPin 6 (I6)
|
#define SpeedPin 6 (I6)
|
||||||
#define DirectionPin 15 //PC1; (A1)
|
#define DirectionPin 15 //PC1; (A1)
|
||||||
|
|
||||||
//from ramps 1.4 stepper driver
|
//from ramps 1.4 stepper driver
|
||||||
#define STEP_PIN 3 //PD3 (INT1) (I3)
|
#define STEP_PIN 3 //PD3 (INT1) (I3)
|
||||||
#define DIR_PIN 14 //PC0; (A0)
|
#define DIR_PIN 14 //PC0; (A0)
|
||||||
//#define ENABLE_PIN 13 //PB5; for now is USELESS (I13)
|
//#define ENABLE_PIN 13 //PB5; for now is USELESS (I13)
|
||||||
|
|
||||||
//to use current motor as speed control, the LMD18245 has 4 bit cuttent output
|
//to use current motor as speed control, the LMD18245 has 4 bit cuttent output
|
||||||
//#define M0 9 //assign 4 bit from PORTB register to current control -> Bxx0000x (x mean any)
|
//#define M0 9 //assign 4 bit from PORTB register to current control -> Bxx0000x (x mean any)
|
||||||
//#define M1 10 // PB1; PB2; PB3; PB4
|
//#define M1 10 // PB1; PB2; PB3; PB4
|
||||||
//#define M2 11
|
//#define M2 11
|
||||||
//#define M3 12
|
//#define M3 12
|
||||||
|
|
||||||
|
|
||||||
volatile long encoder0Pos = 0;
|
volatile long encoder0Pos = 0;
|
||||||
|
|
||||||
long target = 0;
|
long target = 0;
|
||||||
long target1 = 0;
|
long target1 = 0;
|
||||||
int amp=212;
|
int amp=212;
|
||||||
//correction = Kp * error + Kd * (error - prevError) + kI * (sum of errors)
|
//correction = Kp * error + Kd * (error - prevError) + kI * (sum of errors)
|
||||||
//PID controller constants
|
//PID controller constants
|
||||||
float KP = 6.0 ; //position multiplier (gain) 2.25
|
float KP = 6.0 ; //position multiplier (gain) 2.25
|
||||||
float KI = 0.1; // Intergral multiplier (gain) .25
|
float KI = 0.1; // Intergral multiplier (gain) .25
|
||||||
float KD = 1.3; // derivative multiplier (gain) 1.0
|
float KD = 1.3; // derivative multiplier (gain) 1.0
|
||||||
|
|
||||||
int lastError = 0;
|
int lastError = 0;
|
||||||
int sumError = 0;
|
int sumError = 0;
|
||||||
|
|
||||||
//Integral term min/max (random value and not yet tested/verified)
|
//Integral term min/max (random value and not yet tested/verified)
|
||||||
int iMax = 100;
|
int iMax = 100;
|
||||||
int iMin = 0;
|
int iMin = 0;
|
||||||
|
|
||||||
long previousTarget = 0;
|
long previousTarget = 0;
|
||||||
long previousMillis = 0; // will store last time LED was updated
|
long previousMillis = 0; // will store last time LED was updated
|
||||||
long interval = 5; // interval at which to blink (milliseconds)
|
long interval = 5; // interval at which to blink (milliseconds)
|
||||||
|
|
||||||
//for motor control ramps 1.4
|
//for motor control ramps 1.4
|
||||||
bool newStep = false;
|
bool newStep = false;
|
||||||
bool oldStep = false;
|
bool oldStep = false;
|
||||||
bool dir = false;
|
bool dir = false;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
pinModeFast(2, INPUT);
|
pinModeFast(2, INPUT);
|
||||||
pinModeFast(encoder0PinA, INPUT);
|
pinModeFast(encoder0PinA, INPUT);
|
||||||
pinModeFast(encoder0PinB, INPUT);
|
pinModeFast(encoder0PinB, INPUT);
|
||||||
|
|
||||||
pinModeFast(DirectionPin, OUTPUT);
|
pinModeFast(DirectionPin, OUTPUT);
|
||||||
//pinMode(SpeedPin, OUTPUT);
|
//pinMode(SpeedPin, OUTPUT);
|
||||||
|
|
||||||
//ramps 1.4 motor control
|
//ramps 1.4 motor control
|
||||||
pinModeFast(STEP_PIN, INPUT);
|
pinModeFast(STEP_PIN, INPUT);
|
||||||
pinModeFast(DIR_PIN, INPUT);
|
pinModeFast(DIR_PIN, INPUT);
|
||||||
//pinModeFast(M0,OUTPUT);
|
//pinModeFast(M0,OUTPUT);
|
||||||
//pinModeFast(M1,OUTPUT);
|
//pinModeFast(M1,OUTPUT);
|
||||||
//pinModeFast(M2,OUTPUT);
|
//pinModeFast(M2,OUTPUT);
|
||||||
//pinModeFast(M3,OUTPUT);
|
//pinModeFast(M3,OUTPUT);
|
||||||
|
|
||||||
attachInterrupt(0, doEncoderMotor0, CHANGE); // encoder pin on interrupt 0 - pin 2
|
attachInterrupt(0, doEncoderMotor0, CHANGE); // encoder pin on interrupt 0 - pin 2
|
||||||
attachInterrupt(1, countStep, RISING); //on pin 3
|
attachInterrupt(1, countStep, RISING); //on pin 3
|
||||||
|
|
||||||
Serial.begin (115200);
|
Serial.begin (115200);
|
||||||
Serial.println("start"); // a personal quirk
|
Serial.println("start"); // a personal quirk
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(){
|
void loop(){
|
||||||
|
|
||||||
while (Serial.available() > 0) {
|
while (Serial.available() > 0) {
|
||||||
KP = Serial.parseFloat();
|
KP = Serial.parseFloat();
|
||||||
KD = Serial.parseFloat();
|
KD = Serial.parseFloat();
|
||||||
KI = Serial.parseFloat();
|
KI = Serial.parseFloat();
|
||||||
|
|
||||||
|
|
||||||
Serial.println(KP);
|
Serial.println(KP);
|
||||||
Serial.println(KD);
|
Serial.println(KD);
|
||||||
Serial.println(KI);
|
Serial.println(KI);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(millis() - previousTarget > 1000){ //enable this code only for test purposes because it loss a lot of time
|
if(millis() - previousTarget > 1000){ //enable this code only for test purposes because it loss a lot of time
|
||||||
Serial.print(encoder0Pos);
|
Serial.print(encoder0Pos);
|
||||||
Serial.print(',');
|
Serial.print(',');
|
||||||
Serial.println(target1);
|
Serial.println(target1);
|
||||||
previousTarget=millis();
|
previousTarget=millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
target = target1;
|
target = target1;
|
||||||
docalc();
|
docalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void docalc() {
|
void docalc() {
|
||||||
|
|
||||||
if (millis() - previousMillis > interval)
|
if (millis() - previousMillis > interval)
|
||||||
{
|
{
|
||||||
previousMillis = millis(); // remember the last time we blinked the LED
|
previousMillis = millis(); // remember the last time we blinked the LED
|
||||||
|
|
||||||
long error = encoder0Pos - target ; // find the error term of current position - target
|
long error = encoder0Pos - target ; // find the error term of current position - target
|
||||||
|
|
||||||
//generalized PID formula
|
//generalized PID formula
|
||||||
//correction = Kp * error + Kd * (error - prevError) + kI * (sum of errors)
|
//correction = Kp * error + Kd * (error - prevError) + kI * (sum of errors)
|
||||||
long ms = KP * error + KD * (error - lastError) +KI * (sumError);
|
long ms = KP * error + KD * (error - lastError) +KI * (sumError);
|
||||||
|
|
||||||
lastError = error;
|
lastError = error;
|
||||||
sumError += error;
|
sumError += error;
|
||||||
|
|
||||||
//scale the sum for the integral term
|
//scale the sum for the integral term
|
||||||
if(sumError > iMax) {
|
if(sumError > iMax) {
|
||||||
sumError = iMax;
|
sumError = iMax;
|
||||||
} else if(sumError < iMin){
|
} else if(sumError < iMin){
|
||||||
sumError = iMin;
|
sumError = iMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ms > 0){
|
if(ms > 0){
|
||||||
PORTC |=B00000010; //digitalWriteFast2 ( DirectionPin ,HIGH ); write PC1 HIGH (A1)
|
PORTC |=B00000010; //digitalWriteFast2 ( DirectionPin ,HIGH ); write PC1 HIGH (A1)
|
||||||
}
|
}
|
||||||
if(ms < 0){
|
if(ms < 0){
|
||||||
PORTC &=(B11111101); //digitalWriteFast2 ( DirectionPin , LOW ); write PC1 LOW (A1)
|
PORTC &=(B11111101); //digitalWriteFast2 ( DirectionPin , LOW ); write PC1 LOW (A1)
|
||||||
ms = -1 * ms;
|
ms = -1 * ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
int motorspeed = map(ms,0,amp,0,255);
|
int motorspeed = map(ms,0,amp,0,255);
|
||||||
if( motorspeed >= 255) motorspeed=255;
|
if( motorspeed >= 255) motorspeed=255;
|
||||||
//PORTB |=(motorspeed<<1); // is a sort of: digitalwrite(M0 M1 M2 M3, 0 0 0 0 to 1 1 1 1); it set directly PORTB to B**M3M2M1M0*;
|
//PORTB |=(motorspeed<<1); // is a sort of: digitalwrite(M0 M1 M2 M3, 0 0 0 0 to 1 1 1 1); it set directly PORTB to B**M3M2M1M0*;
|
||||||
//analogWrite ( SpeedPin, (255 - motorSpeed) );
|
//analogWrite ( SpeedPin, (255 - motorSpeed) );
|
||||||
analogWrite ( SpeedPin, motorspeed );
|
analogWrite ( SpeedPin, motorspeed );
|
||||||
//Serial.print ( ms );
|
//Serial.print ( ms );
|
||||||
//Serial.print ( ',' );
|
//Serial.print ( ',' );
|
||||||
//Serial.println ( motorspeed );
|
//Serial.println ( motorspeed );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doEncoderMotor0(){
|
void doEncoderMotor0(){
|
||||||
if (((PIND&B0000100)>>2) == HIGH) { // found a low-to-high on channel A; if(digitalRead(encoderPinA)==HIGH){.... read PD2 (I2)
|
if (((PIND&B0000100)>>2) == HIGH) { // found a low-to-high on channel A; if(digitalRead(encoderPinA)==HIGH){.... read PD2 (I2)
|
||||||
|
|
||||||
if ((PINB&B0000001) == LOW) { // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0 (I8)
|
if ((PINB&B0000001) == LOW) { // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0 (I8)
|
||||||
// encoder is turning
|
// encoder is turning
|
||||||
encoder0Pos-- ; // CCW
|
encoder0Pos-- ; // CCW
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
encoder0Pos++ ; // CW
|
encoder0Pos++ ; // CW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // found a high-to-low on channel A
|
else // found a high-to-low on channel A
|
||||||
{
|
{
|
||||||
if ((PINB&B0000001) == LOW) { // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0 (I8)
|
if ((PINB&B0000001) == LOW) { // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0 (I8)
|
||||||
// encoder is turning
|
// encoder is turning
|
||||||
encoder0Pos++ ; // CW
|
encoder0Pos++ ; // CW
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
encoder0Pos-- ; // CCW
|
encoder0Pos-- ; // CCW
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void countStep(){
|
void countStep(){
|
||||||
dir = (PINC&B0000001); // dir=digitalRead(dir_pin) read PC0, 14 digital;
|
dir = (PINC&B0000001); // dir=digitalRead(dir_pin) read PC0, 14 digital;
|
||||||
//here will be (PINB&B0000001) to not use shift in the stable version
|
//here will be (PINB&B0000001) to not use shift in the stable version
|
||||||
if (dir) target1++;
|
if (dir) target1++;
|
||||||
else target1--;
|
else target1--;
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue