Hello again.
First off, thanks for the feedback MarkT.
Sorry for my late reply - unfortunately i dont own a oscilloscope but i hope the readings form my DAQ will do the job.
The first picture (hallsensor uden load) is the hallsensor connected to 5v but with no movement of the motor. The other picture shows the output as i wrap the string around the shaft and pull so a current is induced in the motor and sensor.
It seems like the signal will produce an AMP-reading within half an amp?!? peak to peak= 0,0225V /0,04mv/V = 0,56Amp I dont think that will be satisfactory for me but i am no expert - perhaps my/a filter would be a solution (or make it worse)?
I have tried with several but not sure how big a timeconstant is too big - lack of experience.
Regarding the PWM i can read from the datasheet that the motorboard outputs PWM @ 15kHz. i am signalling the motorboard @ 32kHz from the Arduino (TCCR2B = TCCR2B & 0b11111000 | 0x01) why is that important?
Here is the code so far:
#include <PID_v1.h>
//**************Declaring pins**********
//input/output pins
const int setpointPin = A3; // connected to a pot
const int inputPin = A1; // connected to the Hallsensor
const int outputPin = 3;
const int turnLeftPin = 2; //Directionpin on the motor board.
// Diverse globale variabler
double zeroInput; // sensorreading at atartup or no load
double avgInput; //Calculated average input
double avgSetpoint;
double Setpoint, Input, Output; // PID variables
double Kp; //PID-reg***************
double Ki;
double Kd;
// smooth variables
float ampArray[5];
float ampSort[5];
float amp2;
float ampOut;
const int nrReadings = 5;
// changeble values
unsigned long previousMillis = 0UL; // store timer current value, and start offset
unsigned long inputinterval = 0UL; // speed the loop runs
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
unsigned long serialTime; //this will help us know when to talk with processing
void setup()
{
// Motorcontroller
pinMode(outputPin, OUTPUT);
pinMode(turnLeftPin, OUTPUT);
pinMode(inputPin, INPUT);
pinMode(setpointPin, INPUT);
// Diverse
Serial.begin(9600);
// PWM frekvens
TCCR2B = TCCR2B & 0b11111000 | 0x01; // Timer 2: PWM 3 & 11 @ 31372 Hz the motorboard is specified to want >20kHz
//initialize the variables we're linked to
Setpoint = 0;
zeroInput = analogRead(inputPin);
turnLeftPin, LOW; // before implementing PID in both directions i start with one direction
//Turn the pid on
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(0, 150); //Limits the output
myPID.SetSampleTime(10); // Determines how often the PID algorithm evaluates (default = 200)
}
//**************************LOOP***************************************
void loop() {
// current times since startup
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > inputinterval) {
//previousMillis = currentMillis;
previousMillis += inputinterval;
Motormove();
}
//send-receive with processing if it's time
if(millis()>serialTime)
{
SerialReceive();
SerialSend();
serialTime+=100;
}
}
void Motormove() {
Setpoint = getSetpoint(); //This can be commented out and then changed in processing instead of a pot.
Input = getInput();
myPID.Compute();
analogWrite(outputPin, Output);
}
double getSetpoint() {
double sum;
double avg;
for (int i = 0; i <= nrReadings; i++) {
sum += analogRead(setpointPin);
delayMicroseconds(50);
}
avgSetpoint = sum/nrReadings;
sum = 0;
return avgSetpoint;
}
double getInput() {
double sum;
double avg;
for (int i = 0; i <= nrReadings; i++) {
sum += analogRead(inputPin);
delayMicroseconds(50);
}
avgInput = sum/nrReadings;
sum = 0;
return avgInput;
}
// These functions should give a median but for now i am not using them.
double sortAmpMedian() {
for (int i = 0; i < nrReadings; i++) {
ampSort[i] = ampArray[i];
}
bubbleSort();
bubbleSort();
bubbleSort();
for (int i=0; i < nrReadings; i++) {
ampArray[i] = analogRead(inputPin)-zeroInput;
}
amp2 = 0;
for (int j=1; j<nrReadings-1; j++) {
amp2 += ampSort[j];
}
ampOut = 0;
ampOut = amp2/nrReadings-2;
}
void bubbleSort() {
int out, in;
float swapper;
for(out=0 ; out < 5; out++) { // outer loop
for(in=out; in < 5; in++) { // inner loop
if( ampSort[in] > ampSort[in+1] ) {
// swap them:
swapper = ampSort[in];
ampSort[in] = ampSort[in+1];
ampSort[in+1] = swapper;
}
}
}
}
////*********************************
/********************************************
* Serial Communication functions / helpers
********************************************/
union { // This Data structure lets
byte asBytes[24]; // us take the byte array
float asFloat[6]; // sent from processing and
} // easily convert it to a
foo; // float array
// getting float values from processing into the arduino
// was no small task. the way this program does it is
// as follows:
// * a float takes up 4 bytes. in processing, convert
// the array of floats we want to send, into an array
// of bytes.
// * send the bytes to the arduino
// * use a data structure known as a union to convert
// the array of bytes back into an array of floats
// the bytes coming from the arduino follow the following
// format:
// 0: 0=Manual, 1=Auto, else = ? error ?
// 1: 0=Direct, 1=Reverse, else = ? error ?
// 2-5: float setpoint
// 6-9: float input
// 10-13: float output
// 14-17: float P_Param
// 18-21: float I_Param
// 22-245: float D_Param
void SerialReceive()
{
// read the bytes sent from Processing
int index=0;
byte Auto_Man = -1;
byte Direct_Reverse = -1;
while(Serial.available()&&index<26)
{
if(index==0) Auto_Man = Serial.read();
else if(index==1) Direct_Reverse = Serial.read();
else foo.asBytes[index-2] = Serial.read();
index++;
}
// if the information we got was in the correct format,
// read it into the system
if(index==26 && (Auto_Man==0 || Auto_Man==1)&& (Direct_Reverse==0 || Direct_Reverse==1))
{
Setpoint=double(foo.asFloat[0]);
//Input=double(foo.asFloat[1]); // * the user has the ability to send the
// value of "Input" in most cases (as
// in this one) this is not needed.
if(Auto_Man==0) // * only change the output if we are in
{ // manual mode. otherwise we'll get an
Output=double(foo.asFloat[2]); // output blip, then the controller will
} // overwrite.
double p, i, d; // * read in and set the controller tunings
p = double(foo.asFloat[3]); //
i = double(foo.asFloat[4]); //
d = double(foo.asFloat[5]); //
myPID.SetTunings(p, i, d); //
if(Auto_Man==0) myPID.SetMode(MANUAL);// * set the controller mode
else myPID.SetMode(AUTOMATIC); //
if(Direct_Reverse==0) myPID.SetControllerDirection(DIRECT);// * set the controller Direction
else myPID.SetControllerDirection(REVERSE); //
}
Serial.flush(); // * clear any random data from the serial buffer
}
// unlike our tiny microprocessor, the processing ap
// has no problem converting strings into floats, so
// we can just send strings. much easier than getting
// floats from processing to here no?
void SerialSend()
{
Serial.print("PID ");
Serial.print(Setpoint);
Serial.print(" ");
Serial.print(Input);
Serial.print(" ");
Serial.print(Output);
Serial.print(" ");
Serial.print(myPID.GetKp());
Serial.print(" ");
Serial.print(myPID.GetKi());
Serial.print(" ");
Serial.print(myPID.GetKd());
Serial.print(" ");
if(myPID.GetMode()==AUTOMATIC) Serial.print("Automatic");
else Serial.print("Manual");
Serial.print(" ");
if(myPID.GetDirection()==DIRECT) Serial.println("Direct");
else Serial.println("Reverse");
}
If you made it to here - Thanks again for your time.
Bjorn