Hey guys, I haven’t been properly introduced, specially because I only found out about this forum just now (I know I know, I shouldn’t look for a comunity only when I need help… )
My name is Andre and I started playing with M/C’s a while ago. I have a very basic knowledge of how all this works, and I’m kinda stuck with this project me and a few friends are building.
Basically it is stepper motor and a display. It features 2 buttons to increase/decrease speed and another one to start/stop the spinning.
It should display the speed on an OLED display I got.
So, before I post the code, let me just try to explain what I did and what’s wrong.
I’m using a 20M020D stepper with a DRV8834 driver board. From what I learned, in order to make it spin, I provide a “pulse” to the board:
for (i = 0; i<10; i++) // Iterate for 4000 microsteps.
{
digitalWrite(steppin, LOW); // This LOW to HIGH change is what creates the
digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step.
delayMicroseconds(subdelay); // This delay time is close to top speed for this
}
Ok, very well. But I’m not a fan of using delays, specially because I need several stuff being done at the same time. So I found out about Multi-Threading and the TimedAction Library (http://playground.arduino.cc/Code/TimedAction). In order to use it with MicroSeconds instead of miliseconds, I tweaked it a little and called it TAMicro (that’s what you’re gonna see in the code, but it’s the exact same library only with millis() replaced for micros().
So I used that and pulsed the motor on a given interval, and used a function (included in the library) to change the speed (AKA, the frequency of the pulses). Worked like charm.
The library I’m using to work with the OLED display is the OzOLED (http://blog.oscarliang.net/arduino-oled-display-library/) and also works very well. Since writting on a display is kinda slow, I only update it on a 200ms basis. Also worked well with the motor.
The thing is, when I try everything at the same time, it drags and doesn’t work well (like it spins at 1rpm???).
I tried commenting sections of the code to try to find what part is slowing things down and I can’t really find it. It seems to be everything together that does it, not a single part.
I find it weird because the ATMega328 gets about 1MIPS per MHz. It must be powerfull enough to run this, I just need smart coding (wich I totally suck at!).
You’ll find several weird stuff in there, I’ll try to explain if you have any doubts:
#include <Wire.h>
#include <OzOLED.h>
#include <TAMicro.h>
#include <OneButton.h>
const byte DCR = 4;
const byte ICR = 5;
const byte MODEPin = 6;
const byte M0Pin = 14;
const byte M1Pin = 15;
const byte dirpin = 16;
const byte steppin = 17;
boolean startstop = true;
float rpm = 50;
unsigned long subdelay; // this value is what actually sets the speed on the motor
float stp;
TAMicro Update = TAMicro(200000,updt);
TAMicro Pulse = TAMicro(200000,pulse);
TAMicro Display = TAMicro(200000,displaySpeed);
OneButton increase(ICR, true);
OneButton decrease(DCR, true);
OneButton spinmode(MODEPin, true);
void setup()
{
Serial.begin(9600);
OzOled.init();
pinMode(dirpin, OUTPUT);
pinMode(steppin, OUTPUT);
pinMode(M0Pin, OUTPUT);
pinMode(M1Pin, OUTPUT);
digitalWrite(dirpin, LOW); // LOW = CCW; HIGH = CW rotation
// each button can be clicked, double clicked and long pressed
// resulting on different increases/decreases in the speed (+1, +3, +10rpm, respectively)
increase.attachClick(increase1);
increase.attachDoubleClick(increase3);
increase.attachLongPressStart(increase10);
increase.setClickTicks(300);
increase.setPressTicks(400);
decrease.attachClick(decrease1);
decrease.attachDoubleClick(decrease3);
decrease.attachLongPressStart(decrease10);
decrease.setClickTicks(300);
decrease.setPressTicks(400);
spinmode.attachClick(startStop);
spinmode.setClickTicks(300);
}
// ----------------------------------------------------------------- //
void increase1()
{
rpm++;
if (rpm > 999) rpm = 999;
}
void increase3()
{
rpm+=3;
if (rpm > 999) rpm = 999;
}
void increase10()
{
rpm+=10;
if (rpm > 999) rpm = 999;
}
void decrease1()
{
rpm--;
if (rpm < 50) rpm = 50;
}
void decrease3()
{
rpm-=3;
if (rpm < 50) rpm = 50;
}
void decrease10()
{
rpm-=10;
if (rpm < 50) rpm = 50;
}
void startStop()
{
startstop = !startstop;
if (startstop == false)
{
Pulse.disable();
Serial.println("Stop!");
return;
}
if (startstop == true)
{
Pulse.enable();
Serial.println("Start!");
return;
}
}
// ----------------------------------------------------------------- //
void pulse()
{
digitalWrite(steppin, LOW);
digitalWrite(steppin, HIGH);
}
//This is weird stuff, but it has to do with not completely deleting the screen,
//which would take a "long" time to do. This way is much faster just to rewrite what's needed
void displaySpeed()
{
OzOled.setCursorXY(0, 0);
OzOled.printNumber(rpm);
if (rpm < 100)
{
OzOled.setCursorXY(2, 0);
OzOled.printString(" ");
}
OzOled.setCursorXY(3, 0);
OzOled.printString("rpm");
}
//This function works as a gear shifter, depending on the speed,
//it uses the proper microstepping
void updt()
{
if (rpm >= 600)
{
stp = 1;
digitalWrite(M0Pin, LOW);
digitalWrite(M1Pin, LOW);
}
else if (rpm >= 350 && rpm < 600)
{
stp = 0.5;
digitalWrite(M0Pin, HIGH);
digitalWrite(M1Pin, LOW);
}
else if (rpm < 350)
{
stp = 0.03125;
pinMode(M0Pin, INPUT);
digitalWrite(M1Pin, HIGH);
}
//This formula is what I eventually found out to be accurate to calculate RPM from the delay between pulses
subdelay = ((60000000 * stp) / rpm) / 20;
Pulse.setInterval(subdelay);
Update.setInterval(subdelay); //These 2 lines update the frquency of the pulses and gear shifting
Serial.print(rpm, 0);
Serial.println(" rpm");
}
// ----------------------------------------------------------------- //
void loop()
{
Update.check();
Pulse.check();
Display.check();
increase.tick();
decrease.tick();
spinmode.tick();
}
Please let me know if you need any help understanding what I did there, I have a weird way of coding that should be a lot cleaner.
I really hope to get some help from the pros, this is the biggest project (Yuuuck! What a N00B!!! 8)) I’ve done and it’s driving me crazy!
Thanks in advance!