After some searching around online I am able to run a 2-wire DC motor in a sinusoidal manner. It is a deconstructed printer carriage driven with an Arduino Uno and L298N motor driver. I'm using a potentiometer to control frequency. The code works well but I need help with a few things.
Is there an easy way to control the frequency it runs at? Possibly like setting it to 1.5, 1.6, 1.7,... etc, hertz, and have the sine function run motor? I am currently measuring the hertz but I am not able to get it to run accurately at intervals.
Is there a more elegant way to control the reversing of direction? I am reversing when the sin wave reaches its minimum. But at lower frequencies it will stay at minimum for a few samples and sometimes my method doesn't work... I am currently counting the samples at certain speeds and hard coding that count to reverse.
#define enA 9
#define in1 6
#define in2 7
#define INTERVAL 1000 // time between reads
int val;
int dir;
int count;
unsigned long lastRead = 0;
int frequency = 0;
int times = 0;
int sample_count = 0;
int sensorPin = 0; // The potentiometer is connected to
// analog pin 0
void setup() {
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
// Set initial rotation direction
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
Serial.begin(9600);
}
void reverseMotor(int pwnOutput) {
/* reserse the motor direction
uses the pwm outpur from the sine function
*/
if (dir == 0) {
Serial.println("LEFT <<<<<<<<<<<<<<<<<<<<<<<<<");
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
dir = 1;
} else if (dir == 1) {
Serial.println("RIGHT >>>>>>>>>>>>>>>>>>>>>>>>");
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
dir = 0;
}
analogWrite(enA, pwnOutput);
sample_count++;
}
void runMotor(int pwnOutput) {
analogWrite(enA, pwnOutput);
sample_count++;
}
void loop() {
static uint16_t phase;
int sensorValue;
int adjusting_speed;
int reverse_fix;
sensorValue = analogRead(sensorPin);
phase = (map(sensorValue, 0, 1023, 1, 256));
uint16_t sin_wave[phase];
for (int16_t i = 0; i < (phase); i++) {
float angle = TWO_PI * i / phase;
int16_t val = sin(angle) * (1024 - 1);
int pwmOutput;
int dir;
val += 1024;
sin_wave[i] = val;
pwmOutput = map(val, 0, 2047, 100, 255); // mapping higher than
// 0 to ensure motor is
// still moving,
Serial.println(pwmOutput);
//Serial.println(phase);
//Serial.println(val);
if (pwmOutput != 100) {
runMotor(pwmOutput);
count = 0;
} else {
count++;
// THERE HAS GOT TO BE A BETTER WAY TO DO THIS
if (phase >= 1 && phase <= 32) {
reverse_fix = 1;
}
if (phase >= 33 && phase <= 54) {
reverse_fix = 2;
}
if (phase >= 55 && phase <= 72) {
reverse_fix = 3;
}
if (phase >= 73 && phase <= 91) {
reverse_fix = 4;
}
if (phase >= 92 && phase <= 109) {
reverse_fix = 5;
}
if (phase >= 110 && phase <= 127) {
reverse_fix = 6;
}
if (phase >= 128 && phase <= 156) {
reverse_fix = 7;
}
if (phase >= 157 && phase <= 174) {
reverse_fix = 8;
}
if (phase >= 175 && phase <= 193) {
reverse_fix = 9;
}
if (phase >= 194 && phase <= 207) {
reverse_fix = 10;
}
if (phase >= 208 && phase <= 233) {
reverse_fix = 11;
}
if (phase >= 234 && phase <= 256) {
reverse_fix = 12;
}
if (count >= reverse_fix) {
reverseMotor(pwmOutput);
}
}
}
if (millis() - lastRead >= INTERVAL) { // if INTERVAL has passed
/*
Counting and measuring hertz
*/
val = frequency;
times++;
float vals = val / times;
float hertz = float(sample_count) / float(phase);
lastRead = millis();
Serial.println();
Serial.println("Hz:");
Serial.println(hertz);
Serial.println();
sample_count = 0;
}
}
I am new to Arduino, so any help or advice is appreciated.