Closed fl380 closed 6 years ago
Nice work! At a glance it all looks correct.
Does it fail to zero the second group of motors?
If you make minimal code changes to stop driving the first motor group, but keep the wiring the same, does the 2nd motor group work? I'm thinking about how to isolate what the minimal change is that demonstrates the failure.
The 2nd group doesn’t even zero. I’ll try a few code changes to isolate the issue but if you think of anything else in the meantime, please let me know.
After some testing it appears that updates are not being sent to the 2nd group.
entering "4400=1000:" in the serial console should update the 1st motor of the 2nd group however the 1st motor of the 1st group is updated, similarly "4500=1000:" should update the 2nd motor of the 2nd group but the 2nd motor of the 1st group is updated etc. I've confirmed that the OutputGaugeData() function is switching to the correct case.
Any suggestions?
This is version
I have resolved the original problem which seemed to be an issue with the switch statements and I have tried to optimise the code as much as my limited skills allow.
I however have a new problem whenever there is a stream of rapidly changing values, the stepper motors will suddenly revert to a lower value and then recover to the correct value. I tried increasing the number of "motor updates" which doesn't seem to make any difference. I have also checked the multimap calculations and confirmed that there are no errors in the serial data stream or the mapped values. I hope that my explanation is understandable?
//#################################
//Duct Pressure Left 4500
//Duct Pressure Right 4600
//Cabin Alt 4200
//Diff Press 4300
//Cabin Climb 4400
//EGT 4100
//Fuel Temp 4000
//----------------------------------
//Battery Power 1100
//AC Power 1200
//---------------------------------
//ELEC Display 5000
//---------------------------------
//FLT ALT 6200
//Land ALT 6100
//---------------------------------
//Calibrate Mode
//Pin D8 to GND
//
//Potentiometer Red Wire 5V
//Potentiometer White Wire GND
//Potentiometer Wiper 4000 A0 4100 A1 etc
//
//LCD connects to SDA and SCL pins
//#################################
#include <SoftEasyTransfer.h>
#include <SoftwareSerial.h>
#include <multiMap.h>
#include <SwitecX12.h>
#include "Wire.h" // For I2C LCD Display
#include "LCD.h" // For LCD LCD Display
#include "LiquidCrystal_I2C.h"
//#define CALIBRATE //uncomment to calibrate steppers
#pragma region Calibration
#ifdef Calibration
unsigned int CalMode0 = HIGH;
unsigned int CalMode1 = HIGH;
unsigned int CalMode2 = HIGH;
unsigned int CalMode3 = HIGH;
unsigned int CalMode4 = HIGH;
unsigned int CalMode5 = HIGH;
unsigned int CalMode6 = HIGH;
#endif
#pragma endregion
#pragma region Serial Data
unsigned int pair_key = 0; //incoming data key
long pair_value = 0L; //incoming data value
unsigned int ID = 0;
const byte numChars = 30; //Max no of char
char receivedChars[numChars]; // an array to store the received data
char tempChars[numChars]; //an array for temp data
char * strtokIndx;
boolean newData = false; //clears the data
#pragma endregion
#pragma region LCD
//Set the pins on the I2C chip used for LCD connections ADDR,EN,R/W,RS,D4,D5,D6,D7
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7);
char TopRow[21];
char BottomRow[21];
#pragma endregion
#pragma region Easy Transfer
SoftwareSerial mySerial(2, 3);
SoftEasyTransfer ET;
struct SEND_DATA_STRUCTURE {
unsigned int ID;
long Value;
};
SEND_DATA_STRUCTURE mydata;
#pragma endregion
#pragma region Stepper Motor
#define STEPS (315*12)
const unsigned int NUM_MOTORS_A = 4;
const unsigned int STEPA[NUM_MOTORS_A] = { 22, 24, 26, 28 };
const unsigned int DIRA[NUM_MOTORS_A] = { 23, 25, 27, 29 };
const unsigned int NUM_MOTORS_B = 3;
const unsigned int STEPB[NUM_MOTORS_B] = { 30, 32, 34 };
const unsigned int DIRB[NUM_MOTORS_B] = { 31, 33, 35 };
const unsigned int RESET_A = 9;
const unsigned int RESET_B = 10;
#pragma endregion
#pragma region Mapping
//Fuel Temp 4000
int M0in[] = { -50, -40, -20, 0, 20, 40, 50 };
int M0out[] = { 177, 509, 1108, 1736, 2346, 2952, 3255 };
#define M0size sizeof(M0in)
//EGT 4100
word M1in[] = { 0, 200, 400, 600, 800, 1000 };
word M1out[] = { 147, 835, 1433, 2054, 2634, 3218 };
#define M1size sizeof(M1in)
//Cabin ALT 4200
unsigned long M2in[] = { 0, 5000, 10000, 15000, 20000, 25000, 30000, 32500, 35000, 37500, 40000 };
unsigned long M2out[] = { 22, 945, 1522, 2091, 2638, 2974, 3310, 3403, 3491, 3569, 3665 };
#define M2size sizeof(M2in)
//Diff Pressure 4300
word M3in[] = { 0, 2000, 4000, 6000, 8000, 9000 };
word M3out[] = { 59, 853, 1659, 2446, 3218, 3591 };
#define M3size sizeof(M3in)
//Cabin Climb 4400
int M4in[] = { -3400, -3000, -2000, -1000, -500, 0, 500, 1000, 2000, 3000, 3400 };
int M4out[] = { 0, 156, 456, 816, 1356, 1888, 2448, 2992, 3368, 3664, 3768 };
#define M4size sizeof(M4in)
//Duct Pressure Right 4500
word M5in[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80 };
word M5out[] = { 520, 944, 1304, 1672, 2036, 2376, 2740, 3072, 3400 };
#define M5size sizeof(M5in)
//Duct Pressure Left 4600
word M6in[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80 };
word M6out[] = { 594, 964, 1322, 1707, 2050, 2390, 2730, 3085, 3451 };
#define M6size sizeof(M6in)
#pragma endregion
#pragma region SwitecX12
SwitecX12 BankA[NUM_MOTORS_A] = {
SwitecX12(STEPS, STEPA[0], DIRA[0]),
SwitecX12(STEPS, STEPA[1], DIRA[1]),
SwitecX12(STEPS, STEPA[2], DIRA[2]),
SwitecX12(STEPS, STEPA[3], DIRA[3]),
};
SwitecX12 BankB[NUM_MOTORS_B] = {
SwitecX12(STEPS, STEPB[0], DIRB[0]),
SwitecX12(STEPS, STEPB[1], DIRB[1]),
SwitecX12(STEPS, STEPB[2], DIRB[2]),
};
#pragma endregion
void setup() {
Serial.begin(115200);
Serial.setTimeout(10);
#pragma region LCD
lcd.begin(20, 4);
lcd.setBacklightPin(3, POSITIVE); // BL, BL_POL
lcd.setBacklight(LOW); //Backlight off
#pragma endregion
#pragma region Stepper
digitalWrite(RESET_A, HIGH);
digitalWrite(RESET_B, HIGH);
delay(10);
zeroAll();
#pragma endregion
#pragma region Easy Transfer
mySerial.begin(9600);
ET.begin(details(mydata), &mySerial);
mydata.ID = 4; mydata.Value = 0; //set AC Power Off to clear displays
ET.sendData();
#pragma endregion
#pragma region Calibration
#ifdef Calibration
pinMode(40, INPUT_PULLUP);
pinMode(41, INPUT_PULLUP);
pinMode(42, INPUT_PULLUP);
pinMode(43, INPUT_PULLUP);
pinMode(44, INPUT_PULLUP);
pinMode(45, INPUT_PULLUP);
pinMode(46, INPUT_PULLUP);
#endif
#pragma endregion
}
void zeroAll() {
//for (int i = 0; i < NUM_MOTORS_A; i++) { BankA[i].currentStep = BankA[i].steps - 1; BankA[i].setPosition(0); }
for (auto & i : BankA) { i.currentStep = i.steps - 1; i.setPosition(0); }
bool doneA = false;
while (!doneA) {
doneA = true;
for (auto & i : BankA) { i.update(); doneA &= i.stopped; } //for (int i = 0; i < NUM_MOTORS_A; i++) {BankA[i].update(); doneA &= BankA[i].stopped; }
}
for (auto & i : BankB) { i.currentStep = i.steps - 1; i.setPosition(0); }
bool doneB = false;
while (!doneB) {
doneB = true;
for (auto & i : BankB) { i.update(); doneB &= i.stopped; }
}
}
void loop() {
RecData();
ProcessData();
UpdateMotorsA();
UpdateMotorsB();
#ifdef CALIBRATE
CalMode0 = digitalRead(40);
CalMode1 = digitalRead(41);
CalMode2 = digitalRead(42);
CalMode3 = digitalRead(43);
CalMode4 = digitalRead(44);
CalMode5 = digitalRead(45);
CalMode6 = digitalRead(46);
if (CalMode0 == LOW) {
Calibrate();
}
if (CalMode1 == LOW) {
Calibrate();
}
if (CalMode2 == LOW) {
Calibrate();
}
if (CalMode3 == LOW) {
Calibrate();
}
if (CalMode4 == LOW) {
Calibrate();
}
if (CalMode5 == LOW) {
Calibrate();
}
if (CalMode6 == LOW) {
Calibrate();
}
#endif
}
void UpdateMotorsA() {
//for (int i = 0; i < NUM_MOTORS_A; i++) { BankA[i].update(); }
for (auto & i : BankA) { i.update(); }
}
void UpdateMotorsB() {
for (auto & i : BankB) { i.update(); }
}
void RecData() {
static byte ndx = 0;
char endMarker = ':';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '|';
ndx = 0;
newData = true;
}
}
}
void ProcessData() {
if (newData == true) {
strcpy(tempChars, receivedChars);
strtokIndx = strtok(tempChars, "=");
pair_key = atoi(strtokIndx);
strtokIndx = strtok(nullptr, "=");
pair_value = atol(strtokIndx);
pair_value = (long)pair_value;
unsigned int ID1 = (pair_key % 10000) / 1000;
if (ID1 == 1) { Status(); }
if (ID1 == 4) { Gauges(); }
if (ID1 == 5) { Elec(); }
if (ID1 == 6) { FLT_Land(); }
newData = false;
}
}
void Status() {
ID = ((pair_key % 1000) / 100); //reads second digit of key
if (ID == 1) { lcd.setBacklight(pair_value); mydata.ID = 3; mydata.Value = pair_value; }
if (ID == 2) { mydata.ID = 4; mydata.Value = pair_value; }
ET.sendData();
}
void Gauges() {
unsigned int ID2 = ((pair_key % 1000) / 100); //reads second digit of key
if (ID2 == 0) { BankA[0].setPosition(multiMap<int>(pair_value, M0in, M0out, M0size)); UpdateMotorsA(); }
if (ID2 == 1) { BankA[1].setPosition(multiMap<word>(pair_value, M1in, M1out, M1size)); UpdateMotorsA(); }
if (ID2 == 2) { BankA[2].setPosition(multiMap<unsigned long>(pair_value, M2in, M2out, M2size)); UpdateMotorsA(); }
if (ID2 == 3) { BankA[3].setPosition(multiMap<word>(pair_value, M3in, M3out, M3size)); UpdateMotorsA(); }
if (ID2 == 4) { BankB[0].setPosition(multiMap<int>(pair_value, M4in, M4out, M4size)); UpdateMotorsB(); }
if (ID2 == 5) { BankB[1].setPosition(multiMap<word>(pair_value, M5in, M5out, M5size)); UpdateMotorsB(); }
if (ID2 == 6) { BankB[2].setPosition(multiMap<word>(pair_value, M6in, M6out, M6size)); UpdateMotorsB(); }
}
void FLT_Land() {
unsigned int ID2 = ((pair_key % 1000) / 100); //reads second digit of data key
mydata.ID = ID2;
mydata.Value = pair_value;
ET.sendData();
}
void Elec() {
String PROGMEM dataChars = strtokIndx;
String PROGMEM UL = getStringPartByNum(dataChars, '|', 0);
String PROGMEM UR = getStringPartByNum(dataChars, '|', 1);
String PROGMEM LL = getStringPartByNum(dataChars, '|', 2);
String PROGMEM LC = getStringPartByNum(dataChars, '|', 3);
String PROGMEM LR = getStringPartByNum(dataChars, '|', 4);
if (UL == "NO FAULTS") { UR = " "; LL = "STORED"; }
snprintf(TopRow, 21, "%4s%16s", UL.c_str(), UR.c_str());
snprintf(BottomRow, 21, "%4s%8s%8s", LL.c_str(), LC.c_str(), LR.c_str());
lcd.setCursor(0, 0); lcd.print(TopRow);
lcd.setCursor(0, 3); lcd.print(BottomRow);
memset(receivedChars, 0, sizeof(receivedChars));
memset(tempChars, 0, sizeof(tempChars));
}
String getStringPartByNum(String data, char separator, unsigned int index)
{
unsigned int stringData = 0; //variable to count data part nr
String PROGMEM dataPart = ""; //variable to hold the return text
for (unsigned int i = 0; i < data.length() - 1; i++) { //Walk through the text one letter at a time
if (data[i] == separator) { stringData++; }//Count the number of times separator character appears in the text
else if (stringData == index) { dataPart.concat(data[i]); }//get the text when separator is the right one
else if (stringData > index) { return dataPart; break; }//return text and stop if the next separator appears - to save CPU-time
}
//return text if this is the last part
return dataPart;
}
#ifdef CALIBRATE
void Calibrate() {
if (CalMode0 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankA[0].setPosition(position);
if (BankA[0].currentStep == BankA[0].targetStep) { Serial.print("motor 4000 position = "); Serial.println(position); }
UpdateMotorsA();
}
if (CalMode1 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankA[1].setPosition(position);
if (BankA[1].currentStep == BankA[1].targetStep) { Serial.print("motor 4100 position = "); Serial.println(position); }
UpdateMotorsA();
}
if (CalMode2 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankA[2].setPosition(position);
if (BankA[2].currentStep == BankA[2].targetStep) { Serial.print("motor 4200 position = "); Serial.println(position); }
UpdateMotorsA();
}
if (CalMode3 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankA[3].setPosition(position);
if (BankA[3].currentStep == BankA[3].targetStep) { Serial.print("motor 4300 position = "); Serial.println(position); }
UpdateMotorsA();
}
if (CalMode4 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankB[0].setPosition(position);
if (BankB[0].currentStep == BankB[0].targetStep) { Serial.print("motor 4400 position = "); Serial.println(position); }
UpdateMotorsB();
}
if (CalMode5 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankB[1].setPosition(position);
if (BankB[1].currentStep == BankB[1].targetStep) { Serial.print("motor 4500 position = "); Serial.println(position); }
UpdateMotorsB();
}
if (CalMode6 == LOW) {
unsigned int PotValue = analogRead(A0);
unsigned int position = map(PotValue, 0, 1023, 0, 315 * 12);
BankB[2].setPosition(position);
if (BankB[2].currentStep == BankB[2].targetStep) { Serial.print("motor 4600 position = "); Serial.println(position); }
UpdateMotorsB();
}
}
#endif
Nevermind, I found the problem. I wasn't using the correct data type
Hi,
I'll be grateful for assistance please.
I'm attempting to drive 7 stepper motors using the SwitecX12 library and 2 AX1201728SG chips. Individually the chips work fine but as soon as I connect both at the same time, only the motors connected to the first board respond.
Here is my complete sketch, apologies if I have missed something obvious!
regards
Paul,