its a custom board, but the pin assignments are the same (i program it as an arduino zero). I do believe that is my issue -- i don't think i wired it using the correct Chip Select pin for Sercom2. There is no way to change it without a board rev
Honestly, didn't know that was a thing. I'm an electrical engineer, not a software engineer.
Still very interested in how i would do it "proper" next time, and what exactly my mistakes where.
In any case since all i wanted was basic non-critical one-way communication of two variables, i simply wrote my own communication library using morse code. Let it run for a few days, and don't think it messed up yet. In any case, maybe someone will find my morse code communication useful?
MASTER CODE
/*********************************************************************************************************************
Morse Code Communication To 3 Slaves. Recieves Two Values, NOTE 1-13 and DURATION 0-100
Duration of 0 means the Valve Toggle Sets The Duration
*********************************************************************************************************************/
/*********************************************************************************************************************
Pin Definitions & Variables
*********************************************************************************************************************/
#define CLOCK_PIN 81 //SD_SCK
#define DATA_PIN 82 //SD_MOSI For reference, SD_MISO is pin 80
#define SELECT_PIN_A 39
#define SELECT_PIN_B 18
#define SELECT_PIN_C 0
// Morse code for numbers 0-9. Only considering numbers for simplicity.
String morseCode[13] = {
"-----", // 0
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----.", // 9
".-.-.", // 10
".--.-", // 11
".---." // 12
};
/*********************************************************************************************************************
Morse Code Setup
*********************************************************************************************************************/
void MorseSetup() {
pinMode(CLOCK_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
pinMode(SELECT_PIN_A, OUTPUT);
pinMode(SELECT_PIN_B, OUTPUT);
pinMode(SELECT_PIN_C, OUTPUT);
digitalWrite(SELECT_PIN_A, HIGH); // deselect at the beginning
digitalWrite(SELECT_PIN_B, HIGH); // deselect at the beginning
digitalWrite(SELECT_PIN_C, HIGH); // deselect at the beginning
}
/*********************************************************************************************************************
Morse Code Internal Functions
*********************************************************************************************************************/
#define CommunicationSpeed 1 //how fast the clock pulses are. This is controlled my master only. Nothing to change on slave when adjusted here.
void sendMorse(int num) {
if (num < 0 || num > 12) return;
String code = morseCode[num];
Serial.print("Sending: ");
Serial.println(code); // print the Morse code being sent
for (int i = 0; i < code.length(); i++) {
if (code[i] == '.') {
digitalWrite(DATA_PIN, HIGH);
} else {
digitalWrite(DATA_PIN, LOW);
}
pulseClock(); // send clock pulse with data set
}
}
void pulseClock() {
digitalWrite(CLOCK_PIN, LOW);
delay(CommunicationSpeed); //how fast the clock pulses are
digitalWrite(CLOCK_PIN, HIGH);
delay(CommunicationSpeed); //how fast the clock pulses are
}
void sendData(int position, int duration, int selection) {
selectSlave(selection); // select the appropriate slave, Start Transmission
sendMorse(position);
sendMorse(duration / 10); // tens place
sendMorse(duration % 10); // ones place
deselectSlaves(); // deselect all slaves at the end of the communication, End Transmission
}
void selectSlave(int selection) {
digitalWrite(SELECT_PIN_A, HIGH);
digitalWrite(SELECT_PIN_B, HIGH);
digitalWrite(SELECT_PIN_C, HIGH);
switch(selection) {
case 1: digitalWrite(SELECT_PIN_A, LOW); break;
case 2: digitalWrite(SELECT_PIN_B, LOW); break;
case 3: digitalWrite(SELECT_PIN_C, LOW); break;
}
}
void deselectSlaves() {
digitalWrite(SELECT_PIN_A, HIGH);
digitalWrite(SELECT_PIN_B, HIGH);
digitalWrite(SELECT_PIN_C, HIGH);
}
/*********************************************************************************************************************
Main Morse Code Function. Call This From Main Program. Sets the position and duration values for the selected PP.
Recieves Position, Duration, Selection. Selection is which of the 3 PP Modules are selected.
Returns 1 for Success, 0 for fail.
*********************************************************************************************************************/
#define POSITION_MIN 0
#define POSITION_MAX 12
#define DURATION_MIN 0
#define DURATION_MAX 12
int MorseCode(int position, int duration, int selection) {
if(position < POSITION_MIN || position > POSITION_MAX ||
duration < DURATION_MIN || duration > DURATION_MAX ||
selection < 1 || selection > 3) {
return 0; // fail due to out-of-bounds input
}
sendData(position, duration, selection); //Send the position, duration, selection values
return 1; // success
}
SLAVE CODE
/*********************************************************************************************************************
Morse Code Communication From Master. Recieves Two Values, NOTE 1-13 and DURATION 0-100
*********************************************************************************************************************/
const int CLOCK_PIN = 3;
const int SELECT_PIN = 8;
const int DATA_PIN = 4;
String receivedMorse = "";
volatile bool newData = false;
bool isReceiving = false;
/*********************************************************************************************************************
Morse Code Setup
*********************************************************************************************************************/
void MorseSetup() {
pinMode(CLOCK_PIN, INPUT);
pinMode(SELECT_PIN, INPUT);
pinMode(DATA_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(SELECT_PIN), selectISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(CLOCK_PIN), clockISR, RISING);
}
/*********************************************************************************************************************
Morse Code Internal Functions
*********************************************************************************************************************/
void selectISR() {
if (digitalRead(SELECT_PIN) == LOW) {
isReceiving = true;
receivedMorse = "";
} else {
isReceiving = false;
newData = true; // Set the flag to signal that new data has been received
}
}
void clockISR() {
if (isReceiving) {
if (digitalRead(DATA_PIN) == HIGH) {
receivedMorse += ".";
} else {
receivedMorse += "-";
}
}
}
String morseCode[13] = {
"-----", // 0
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----.", // 9
".-.-.", // 10
".--.-", // 11
".---." // 12
};
int morseToNumber(String morse) {
for (int i = 0; i < 13; i++) {
if (morse == morseCode[i]) {
return i;
}
}
return -1; // error or not found
}
/*********************************************************************************************************************
Decodes the morse code recieved. Sets the position and duration variables.
Returns "1" if values within range of 1-13 and 0-100 respectively. Returns "0" if they are not.
*********************************************************************************************************************/
#define POSITION_MIN 0
#define POSITION_MAX 12
#define DURATION_MIN 0
#define DURATION_MAX 12
int decodeMorse() {
if (receivedMorse.length() < 10 || receivedMorse.length() > 15) {
Serial.println("Error: Received Morse length mismatch!");
Serial.println(receivedMorse);
return 0;
}
int length = receivedMorse.length();
String positionMorse = receivedMorse.substring(0, 5);
String tensMorse = receivedMorse.substring(5, length - 5);
String onesMorse = receivedMorse.substring(length - 5, length);
position = morseToNumber(positionMorse);
int tens = morseToNumber(tensMorse);
int ones = morseToNumber(onesMorse);
// Serial.print("Decoded: Position: "); // Debugging information
// Serial.print(position);
// Serial.print(", Tens: ");
// Serial.print(tens);
// Serial.print(", Ones: ");
// Serial.println(ones);
duration = tens * 10 + ones;
if (position >= POSITION_MIN && position <= POSITION_MAX && duration >= DURATION_MIN && duration <= DURATION_MAX) {
return 1;
} else {
return 0;
}
}
/*********************************************************************************************************************
Main Morse Code Function. Call This From Main Program. Sets the position and duration values.
Returns 1 = new data 0 = no new data
*********************************************************************************************************************/
int MorseCode() {
if (newData) {
// Serial.println("Received New Data: " + receivedMorse); // Print received Morse code
int isValid = decodeMorse();
newData = false;
return isValid;
} else {
return 0;
}
}