Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
main.cpp
- Committer:
- paologiorgio
- Date:
- 2022-06-09
- Revision:
- 0:c81f86a07902
- Child:
- 1:db73b542b7bc
File content as of revision 0:c81f86a07902:
#include "mbed.h"
#include <math.h>
/*
TO-DO: i dati arrivano in DigitalIn e DigitalOut, anziché essere della classe Serial.
Al fine di poter immagazzinare i dati, associo a determinati livelli logici (1/0) dei caratteri,
riempio il buffer e ritrasmetto con i caratteri riconvertiti
comando per azionamento periferiche: SPARE
*/
// ************* INFO *******************
// master-slave: slave MIMA comunica con DORA con collegamento UART (tx, rx, gnd)
// PC S/C sends packets to DORA -> MIMA (STM32) -> PC
// ------ ------------
// | MIMA | ---- DORA ---- | SPACE/CRAFT |
// ------ ------------
// ************ DEFINE ******************
// definisce dimensione pacchetto inviato da pc
// telecommand: 15 bit + 1 di controllo
#define PACKETSIZE 20 // lunghezza massima della stringa trasmissibile prima di interrupt
#define PACKET 15 // 15 bit, 1 di parità di controllo
#define PACKET_CHECKED 16 // COMMAND IDENTIFIER + TAG + PAYLOAD + PARITY CHECK
#define IDENTIFIER 5
#define TAG 2
#define PAYLOAD 8
#define CMD_NUM 32
#define OPTION_1 10 // 57 * 16
#define OPTION_2 90608 // 5663 * 16
#define tb 7 // bit sampling period
#define BufferXOR 175 // 2800/16 - 1
#define TIMEOUT 15000 // milliseconds
#define word 16
// ************ CN7+USB ******************
Serial SC(USBTX, USBRX); // A4 TX, A6 RX - DATA OUT, DATA IN
// ************** CN10 *******************
Serial MIMA(PC_4, PC_5); // TERZO - TERZULTIMO -> D0 e D1 non vanno bene! Risorse già occupate
// ************** TIMER *****************
Timer t;
// ******* L16 Actuatonix - Relay ********
PwmOut M1 (PA_6); // D12
PwmOut M2 (PA_8); // D7
DigitalOut Relay5V (PA_7); // D11
DigitalOut Relay12V (PB_4); // D5
DigitalOut Relay24V (PB_5); // D4
DigitalOut Relay15_15_5V (PB_10); // D6 | +15, -15, -5
float offset = 0.0f;
volatile char ch;
// DATA_OUT_CLOCK.write(0) -> wait_ms(7) -> DATA_OUT_CLOCK.write(0) -> wait_ms(7)
// *********** VARIABLES *****************
volatile int nIndex; // indice del pacchetto per lo "spacchettamento"
char getPacket[PACKETSIZE]; // buffer - pacchetto inviato di dimensione max PACKETSIZE
char PacketChecked[PACKET_CHECKED]; // lato Space/Craft
char TLM[OPTION_1]; // lato MIMA per check
char TLM_SD[OPTION_2]; // lato MIMA per check
volatile int LEN; // numero di bit da ricevere per ricezione corretta
volatile int commandId;
volatile int payloadDec;
volatile int size;
volatile unsigned char data; // in arrivo da MIMA per telemetria
int base = 2; // base per l'esponenziale (conversione binary to decimal)
int CMD[CMD_NUM]; // CMD in decimale
volatile int option_1 = 0; // default
volatile int option_2 = 0;
int tempCheck[word]; // temp
char checksumWord[word]; // checksum sul pacchetto elaborato
char checksumReceived[word]; // checksum ricevuto
// ************** SETUP *******************
void CMD_REF(); // crea la lista dei comandi
void clearBuffer(char *arr, int arrLen); // ripulisce il buffer di ricezione
void checksum(char *a, int aSize); // effettua checksum
void RxTelecommand();
void TxTelecommand();
void RxTelemetry();
void TxTelemetry();
void ActuatorControl(int command); // controllo L16 e Relay
// *********************************************************************
// ************** MAIN *******************
int main()
{
// baudrate
SC.baud(115200);
MIMA.baud(9600);
// Setup PWM
M1.period_us(1000);
M2.period_us(1000);
// Setup Relay: default (pull-up)
Relay5V = 1;
Relay12V = 1;
Relay15_15_5V = 1; // +15, -15, -5
Relay24V = 1;
// diagnostic
SC.printf("*******Starting... *******\n\r");
// interrupt
SC.attach(&RxTelecommand, Serial::RxIrq);
MIMA.attach(&RxTelemetry, Serial::RxIrq);
}
// *********************************************************************
// ************** FUNCTIONS *******************
void CMD_REF()
{
for (int i = 0; i < CMD_NUM; i++)
{
CMD[i] = i;
}
}
// clear
void clearBuffer(char *arr, int arrLen)
{
// reset pacchetto
nIndex = 0;
for (nIndex = 0; nIndex < arrLen; nIndex++)
{
arr[nIndex] = '\0';
}
}
// DORA riceve telecomando da SC
void RxTelecommand()
{
CMD_REF(); // carica vettore dei comandi
while (SC.readable()) // finché sulla porta USB arrivano dati, esegui
{
clearBuffer(getPacket, sizeof(getPacket) / sizeof(getPacket[0])); // clear the buffer
SC.gets(getPacket, sizeof(getPacket)); // leggi la stringa in ingresso
LEN = strlen(getPacket) - 2; // calcola la sua lunghezza ignorando i tag \r\n
ch = getPacket[0];
if (LEN != PACKET)
{
if (LEN == 1)
{
SC.printf("> Bit number: %i is not equal to 15 // no tele-command\n\r", LEN); // diagnostica
}
}
else
{
for (int n = 0; n < LEN; n++)
{
PacketChecked[n] = getPacket[n]; // riempi il nuovo array
}
// ***CONTROLLO DEI BIT - LSB: EVEN/ODD ***
int ones = 0;
int check = 0;
while (check < PACKET)
{
if (getPacket[check] == '1')
{
ones++;
}
check++;
}
char newItem;
if (ones % 2 == 0)
{
newItem = '0'; // If the number of ones in[B0÷B14] bits is even (making the total number of ones even)
}
else
{
newItem = '1'; // If the number of ones in[B0÷B14] bits is odd (making the total number of ones even)
}
int nPacket = PACKET + 1;
// shift elements
for (int i = nPacket - 1; i >= PACKET_CHECKED; i--)
{
PacketChecked[i] = PacketChecked[i - 1];
}
// insert LSB
PacketChecked[PACKET_CHECKED - 1] = newItem;
SC.printf("> Send: ");
for (int z = 0; z < PACKET_CHECKED; z++)
{
SC.printf("%c", PacketChecked[z]);
}
SC.printf("\n\r");
// ************DIAGNOSTICA ************
// un telecommand è formato da 16 bit. i primi 5 sono identificativi,
// poi ho due bit che mi specificano se i dati in arrivo sono una o più parole,
// dopodiché ho un payload da 8 bit e per concludere ho LSB (parity bit)
// MSB IIII TT PPPPPPPP PC
// ***COMMAND IDENTIFIER ***
int CMDIndex = 0; // puntatore dell'identificativo
commandId = 0;
int B7 = PacketChecked[7];
int B9 = PacketChecked[9];
int B11 = PacketChecked[11];
// trasformo l'identificatore in numero
while (CMDIndex < IDENTIFIER)
{
if (PacketChecked[CMDIndex] == '1')
{
int raise = IDENTIFIER - 1 - CMDIndex;
commandId += pow((float) base, (float) raise);
}
else
{
commandId += 0;
}
CMDIndex++;
}
// scorro la lista di comandi disponibli e verifico se il comando trasmesso rientra
// nella lista, altrimenti finisco in uno dei 3 SPARE
int k = 0;
int isElementPresent = 0;
while (k < CMD_NUM)
{
if (commandId == CMD[k])
{
isElementPresent = 1;
SC.printf("> Telcommand sent belgons to MIMA command list: CMD %i\n\r", k);
if (k == 2 || k == 15 || k == 30) // CMD02, CMD15, CMD30
{
SC.printf("> CMD %i : SPARE\n\r", k);
}
else if (k == 0 && PacketChecked[5] == '0' && PacketChecked[6] == '0') // CMD0 - spare
{
payloadDec = 0; // inizializzazione del payload in formato digitale
int counter = 7; // parto dal settimo bit
while (counter < PACKET)
{
if (PacketChecked[counter] == '1')
{
int raise = PACKET - 1 - counter;
payloadDec += pow((float) base, (float) raise);
}
else
{
payloadDec += 0;
}
counter++;
}
ActuatorControl(payloadDec);
break;
}
else if (k == 1) // CMD01
{
if (PacketChecked[11] == '0' &&
PacketChecked[12] == '0' &&
PacketChecked[13] == '0' &&
PacketChecked[14] == '1')
{
SC.printf("> Setting MIMA... Sleeping mode\n\r");
}
else if (PacketChecked[11] == '0' &&
PacketChecked[12] == '0' &&
PacketChecked[13] == '1' &&
PacketChecked[14] == '0')
{
SC.printf("> Setting MIMA... Awake mode\n\r");
}
else if (PacketChecked[11] == '0' &&
PacketChecked[12] == '0' &&
PacketChecked[13] == '1' &&
PacketChecked[14] == '1')
{
SC.printf("> Setting MIMA... Calibration mode\n\r");
}
else if (PacketChecked[11] == '0' &&
PacketChecked[12] == '1' &&
PacketChecked[13] == '0' &&
PacketChecked[14] == '0')
{
SC.printf("> Setting MIMA... Observation mode\n\r");
}
else if (PacketChecked[11] == '0' &&
PacketChecked[12] == '1' &&
PacketChecked[13] == '0' &&
PacketChecked[14] == '1')
{
SC.printf("> Setting MIMA... Auto-test mode\n\r");
}
else if (PacketChecked[11] == '0' &&
PacketChecked[12] == '1' &&
PacketChecked[13] == '1' &&
PacketChecked[14] == '0')
{
SC.printf("> Setting MIMA... Full testing mode\n\r");
}
}
else if (k == 7) // CMD07
{
// IR sensor thermal loop
if (B7 == '1')
{
SC.printf("> IR sensor thermal loop...\n\r");
SC.printf("IRT1 telemetry: feedback signal in the thermal control loop (default). IRT2 only for monitoring\n\r");
}
else
{
SC.printf("> IR sensor thermal loop...\n\r");
SC.printf("IRT2 telemetry: feedback signal in the thermal control. IRT1 only for monitoring\n\r");
}
// Laser Diode thermal loop
if (B9 == '1')
{
SC.printf("> Laser Diode thermal loop...\n\r");
SC.printf("LDT1 telemetry: feedback signal in the thermal control loop (default). LDT2 only for monitoring\n\r");
}
else
{
SC.printf("> Laser Diode thermal loop...\n\r");
SC.printf("LDT2 telemetry: feedback signal in the thermal control. LDT1 only for monitoring\n\r");
}
// BlackBody thermal loop
if (B11 == '1')
{
SC.printf("> BlackBody thermal loop...\n\r");
SC.printf("BBT1 telemetry: feedback signal in the thermal control loop (default). BBT2 only for monitoring\n\r");
}
else
{
SC.printf("> BlackBody thermal loop...\n\r");
SC.printf("BBT2 telemetry: feedback signal in the thermal control. BBT1 only for monitoring\n\r");
}
}
}
k++;
}
if (isElementPresent == '0')
{
SC.printf("Telecommand sent doesn't exist\n\r");
}
// ***TAG ***
int B5 = PacketChecked[5];
int B6 = PacketChecked[6];
if (B5 == '0' && B6 == '0')
{
// Single word telemetry
SC.printf("Single word telemetry\n\r");
}
else if (B5 == '0' && B6 == '1')
{
// Multiple words telemetry (1st word)
SC.printf("Multiple words telemetry (1st word)\n\r");
}
else if (B5 == '1' && B6 == '0')
{
// Multiple words telemetry (2nd word)
SC.printf("Multiple words telemetry (2nd word)\n\r");
}
else
{
// Not used
SC.printf("NOT USED\n\r");
}
// ***PAYLOAD ***
SC.printf("> Payload: ");
for (int IndexPayload = 7; IndexPayload < PACKET; IndexPayload++)
{
SC.printf("%c", PacketChecked[IndexPayload]);
}
SC.printf("\n\r"); // per leggibilità
//***********FINE DIAGNOSTICA PACCHETTO***********
}
TxTelecommand();
}
}
/* ***************************************************************** */
// DORA trasmette telecomando a MIMA
void TxTelecommand()
{
for (int i = 0; i < PACKET_CHECKED + 1; i++)
{
MIMA.putc(PacketChecked[i]);
}
}
/* ***************************************************************** */
// DORA riceve telemetrie/telemetrie+scientific data da MIMA
void RxTelemetry()
{
// aggiungere timeout, perché non so se raggiungo il numero dei caratteri
while (MIMA.readable())
{
t.start();
// char prova = MIMA.getc();
// SC.printf("> Text: %c\n\r", prova);
// check del payload per scelta del buffer
// 00000000 -> Option 1: transfer all Housekeeping and Status telemetries (from TLM00 to TLM56)
// 11111111 -> Option 2: transfer telemetries and scientific data packets (from TLM00 to TLM5662)
int j = 7;
while (j < PACKET_CHECKED)
{
if (PacketChecked[j] == '0')
{
j++;
}
else
{
option_1 = 1;
break;
}
}
int k = 7;
while (k < PACKET_CHECKED)
{
if (PacketChecked[k] == '1')
{
k++;
}
else
{
option_2 = 1;
break;
}
}
if (commandId == 5) // TLMODE
{
// STARTCH1 - 2800 scientific points - CHECKSUM - ENDCH1
// STARTCH2 - 2800 scientific points - CHECKSUM - ENDCH2
// 5606 words
if (option_1 == 0)
{
size = 0; // reset
clearBuffer(TLM, sizeof(TLM) / sizeof(TLM[0]));
if (t.read() < TIMEOUT)
{
while (size < OPTION_1)
{
data = MIMA.getc(); // prendi carattere in arrivo
TLM[size++] = data;
}
}
else
{
t.stop();
SC.printf("> Time elapsed: %.2f\n\r", t.read());
clearBuffer(TLM, sizeof(TLM) / sizeof(TLM[0]));
}
}
else if (option_2 == 0)
{
size = 0;
clearBuffer(TLM_SD, sizeof(TLM_SD) / sizeof(TLM_SD[0]));
t.start();
if (t.read() < TIMEOUT)
{
while (size < OPTION_2)
{
data = MIMA.getc(); // prendi carattere in arrivo
TLM_SD[size++] = data;
}
//checksum(TLM_SD, OPTION_2);
}
else
{
t.stop();
clearBuffer(TLM_SD, sizeof(TLM_SD) / sizeof(TLM_SD[0]));
}
}
TxTelemetry();
}
}
}
/* ***************************************************************** */
// integrità dei dati ricevuti da MIMA
void checksum(char *a, int aSize)
{
volatile int temp;
volatile int var;
volatile int p = 0;
for (int i = word; i < 2*word; i++)
{
for (int j = 2*i; j < aSize; j+=i)
{
if (j == 2*i)
{
temp = (int)(a[i] ^ a[j]);
} else
{
temp = temp ^ (int)a[j];
}
}
tempCheck[p++] = temp; // vettore del checksum in int
}
for (int i = 0; i < word; i++) // trasformo in char
{
if (tempCheck[i] == 0 || tempCheck[i] == 48)
{
checksumWord[i++] = '0';
}
else if (tempCheck[i] == 1 || tempCheck[i] == 49)
{
checksumWord[i++] = '1';
}
}
volatile int t = 0;
// confronto
for (int i = 2801*word; i < 2802*16; i++)
{
checksumReceived[t++] = TLM_SD[i];
}
for (int i = 0; i < word; i++)
{
if (checksumWord[i] != checksumReceived[i])
{
SC.printf("\n\r> ERROR detected: BIT n. %i\n\r", i+1);
break;
}
}
}
/* ***************************************************************** */
// DORA trasmette dati verso Space/craft
void TxTelemetry()
{
// The data are read on the falling-edge of the DATA_CLOCK_OUT signal
if (option_1 == 0)
{
SC.printf("\n\r> Receiving 57 words from MIMA... \n\r");
for (int i = 0; i < OPTION_1; i++)
{
SC.putc(TLM[i]);
}
/*SC.printf("\n\r> Receiving 57 words from DORA... \n\r");
for (int i = 0; i < OPTION_1; i++)
{
ARDUINO.putc(DEVICE.putc(TLM[i]));
}
*/
}
else if (option_2 == 0)
{
SC.printf("Receiving 5663 words...\n\r");
for (int i = 0; i < OPTION_2; i++)
{
SC.putc(TLM_SD[i]);
}
/*
SC.printf("\n\r> Receiving 5663 words from DORA... \n\r");
for (int i = 0; i < OPTION_2; i++)
{
ARDUINO.putc(DEVICE.putc(TLM_SD[i]));
}
*/
}
}
/* ***************************************************************** */
// controllo dell'attuatore e dei relay
void ActuatorControl(int command)
{
SC.printf("\n\r *** L16 ACTUATONIX - RELAY CONTROL *** \n\r"); // leggibilità
// *** estensione/ritrazione dell'attuatore ***
if((command == 128) && (offset < 1.0f)) {
offset += 0.2f;
} else if((command == 64) && (offset > 0.0f)) {
offset -= 0.2f;
// *** gestione accensione/spegnimento relay alimentazione ***
} // Relay 5V
else if (command == 1) {
Relay5V = 0;
SC.printf("\r\nRelay 5V ON\r\n");
} else if (command == 0) {
Relay5V = 1;
SC.printf("\r\nRelay 5V OFF\r\n");
// Relay 12V
} else if (command == 3) {
Relay12V = 0;
SC.printf("\r\nRelay 12V ON\r\n");
} else if (command == 2) {
Relay12V = 1;
SC.printf("\r\nRelay 12V OFF\r\n");
// Relay +15V, -15V, -5V
} else if (command == 7) {
Relay15_15_5V = 0;
SC.printf("\r\nRelay +15V, -15V, -5V ON\r\n");
} else if (command == 6) {
Relay15_15_5V = 1;
SC.printf("\r\nRelay +15V, -15V, -5V OFF\r\n");
// Relay 24V
} else if (command == 15) {
Relay24V = 0;
SC.printf("\r\nRelay 24V ON\r\n");
} else if (command == 8) {
Relay24V = 1;
SC.printf("\r\nRelay 24V OFF\r\n");
// RESET
} else if (command == 255) {
// spegni tutto
Relay5V = 1;
Relay12V = 1;
Relay15_15_5V = 1; // +15, -15, -5
Relay24V = 1;
}
M1.write(offset);
M2.write(offset);
SC.printf("> Duty Cycle %.2f / estensione \n \r", offset);
}