This is a perplexing problem to me. I am new to Arduinos.
I have an Arduino Mega with an Adafruit motor shield (Adafruit Motor/Stepper/Servo Shield for Arduino v2 Kit [v2.3] : ID 1438 : $19.95 : Adafruit Industries, Unique & fun DIY electronics and kits) on it.
For now, I want two devices connected to it -
-
A servo motor that I want to position in the usual fashion, to some point between 0 and 180 degrees. It has its own power supply.
-
A vibratory motor (in a dispensing device) that functions at different speeds, based on the voltage (0 - 3 V) applied to it. It has its own 5 V power supply, separate from the one for the servo, but 5V will (eventually) cook it, so I'm using PWM via analogWrite() to reduce that to a safe level and to exert fine control how much voltage in the 0-3V range is applied to it.
Both devices are both controlled by serial commands received from the computer. It's a simple one-way communication protocol:
If I send ">S123<" to the Arduino, it puts the servo at 123 deg.
If I send ">V255<" to the Arduino, it calls analogWrite to put up 5V to the drain pin, and the vibratory motor sees a 0V potential and is off.
If I send ">V102<" to the Arduino, it calls analogWrite to put up 2V to the drain pin (102 / 255 * 5), and the vibratory motor sees a 3V potential and runs at full speed. ">V153"< gets it to 2V and a slower speed, etc.
Both features work separately. The servo moves as expected. The potential measured between the vibratory motor power supply (+5V) and the drain pin (#45) is also exactly as expected.
The problem is when I have both features in the same program. In this case, the servo still works just fine, but no matter what value analogWrite( 45, [0-254] ) calls, the measured potential is always 5 V, and analogWrite( 45, 255 ) cuts the potential to 0 V.
It appears to me that something about setting up and using the servo breaks the PWM on pin 45.
The following is Arduino code that functions properly to set the voltage to the vibrating dispensing motor.
After that is a labeled photo to illustrate the part arrangement and wiring, on the off chance it's helpful and exposes a mistake I'm making there.
If I uncomment out the lines related to the servo ... the servo functions properly, but now the voltage to the vibrating dispenser motor appears to be an ALL OR NONE result. ">V255<" results in 0V but any number from 0 - 254 results in 5V.
What gives?
Thank you.
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <Servo.h>
#include <ctype.h>
//Adafruit_MotorShield AFMS = Adafruit_MotorShield();
//Adafruit_StepperMotor *myStepper = AFMS.getStepper(200, 2);
//Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
//Servo servo1;
void setup() {
pinMode (45, OUTPUT);
analogWrite( 45, 255 ); // ensure V motor is OFF at startup
Serial.begin(115200);
// AFMS.begin();
// servo1.attach(10);
}
void loop() {
char c_start, c_end;
char command_name, command_data[4];
int command_data_value;
// read from serial port until beginning of command is received
while( 1 ) {
c_start = Serial.read(); delay(2);
if( c_start == '>' ) break;
}
// get the rest of the command in format >CDDD<
command_name = Serial.read(); delay(2);
command_data[0] = Serial.read(); delay(2);
command_data[1] = Serial.read(); delay(2);
command_data[2] = Serial.read(); delay(2);
command_data[3] = '\0';
c_end = Serial.read(); delay(2);
// is this command formatted properly?
if( (c_start == '>') && (c_end == '<') &&
isalpha(command_name) &&
isdigit(command_data[0]) &&
isdigit(command_data[1]) &&
isdigit(command_data[2]) ) {
command_data_value = atoi( command_data );
if( command_name == 'S' ) { // command to position servo
// if( command_data_value < 5 ) servo1.write( 5 );
// else if( command_data_value > 175 ) servo1.write( 175 );
// else servo1.write( command_data_value );
} else if( command_name == 'V' ) { // command to vibratory dispenser
if( command_data_value < 102 ) analogWrite( 45, 102 ); // safe max of 3 V to motor
else if( command_data_value > 255 ) analogWrite( 45, 255 );
else analogWrite( 45, command_data_value );
}
}
}