I am building a test project that uses a dc motor with a quadrature encoder using encoder.h and a rotary encoder using rotaryencoder.h and an Adafruit OLED display. I cannot seem to figure out how to get the display function to work on my arduino mini pro showing both the motor and the rotary position. I have a version working just showing the rotary position but no motor included. My programming knowledge is limited but I am teaching myself as I go so please be gentle.... Any help would be appreciated. My goal is to get the OLED display to show the motor position and rotary position at the time its being moved. My display is I2C which I know can cause some problems with time but hopefully it isnt the one problem here.
My code:
// PID motor position control.
// Thanks to Brett Beauregard for his nice PID library http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/
#include <Encoder.h>
#include <RotaryEncoder.h>
//#include <PinChangeInt.h>
#include <PID_v1.h>
#include <stdio.h>
#include <digitalWriteFast.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Encoder myEnc(3, 4);
//#define encodPinA1 3 // Quadrature encoder A pin
//#define encodPinB1 4 // Quadrature encoder B pin
#define M1 5 // PWM outputs to L298N H-Bridge motor driver module
#define M2 6
RotaryEncoder encoder2(A2, A3);
#define OLED_RESET 8
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
double kp = 4 , ki = 1.5 , kd = 0.2; // modify for optimal performance
double input = 0, output = 0, setpoint = 0;
long temp;
PID myPID(&input, &output, &setpoint, kp, ki, kd, DIRECT); // if motor will only run at full speed try 'REVERSE' instead of 'DIRECT'
unsigned int pos = 0;
unsigned int tick = 0;
unsigned int mark = 0;
volatile long encoderPos = 0;
void draw();
void setup() {
Serial.begin (115200); // for debugging
Serial.println("SimplePollRotator example for the RotaryEncoder library.");
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// init done
// Show image buffer on the display hardware.
// Since the buffer is initialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.display();
delay(1000);
// Clear the buffer.
display.clearDisplay();
// text display tests
tick = pos;
mark = encoderPos;
pinModeFast(5, OUTPUT); //Initiates Motor Channel A pin
pinModeFast(6, OUTPUT); //Initiates Brake Channel A pin
input = myEnc.read();
setpoint = 0;
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
TCCR0B = _BV(CS00);
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(1);
myPID.SetOutputLimits(-255, 255);
}
void draw() {
int enc = tick;
int mtr = mark;
String e = String(enc);
while(e.length() < 3)
e = String('0') + e;
String m = String(mtr);
while(m.length() < 3)
m = String('0') + m;
display.clearDisplay();
display.setFont(NULL);
display.setCursor(0,0);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("Enc:"); display.println(e);
display.print("Motor:"); display.println(m);
display.display();
}
void enc() {
encoder2.tick();
int newPos = encoder2.getPosition();
setpoint = newPos * 4; // modify to fit motor and encoder characteristics, rotary encoder connected
if (pos != newPos) {
pos = newPos;
tick = pos;
}
}
void motorposition() {
input = myEnc.read(); // data from encoder
if (input != encoderPos)
{
encoderPos = input;
mark = encoderPos;
}
}
void loop() {
display.clearDisplay();
enc();
motorposition();
draw();
myPID.Compute(); // calculate new output
pwmOut(output); // drive L298N H-Bridge module
}
void pwmOut(int out) { // to H-Bridge board
if (out > 0) {
analogWrite(M1, out); // drive motor CW
analogWrite(M2, 0);
}
else {
analogWrite(M1, 0);
analogWrite(M2, abs(out)); // drive motor CCW
}
}