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.
I2CSlaveComm.cpp
- Committer:
- gmfortier
- Date:
- 2019-05-06
- Revision:
- 8:e82e5b78dbbd
- Parent:
- 7:8698d17a0168
- Child:
- 9:d2b700d42dbe
File content as of revision 8:e82e5b78dbbd:
#include "mbed.h"
#include "I2CSlaveComm.h"
I2CSlaveCustom slave(D4, D7);
I2CSlaveCustom slave2(D14, D15); //use another I2C to emulate the adc
Ticker command_ticker;
Ticker flow_ticker;
DigitalIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);
Serial PcUart(USBTX, USBRX);
int current_tensiometer = 0; // Two possible sensors with different patterns
float tension;
int modeSwitch = 1;
int saveSwitch = 0;
float counter = 0;
unsigned char PointOnAddress = 0;
char buffer[64];
unsigned char ADCValue[2];
struct CycleValues {
float riseTime;
float fallTime;
float plateauTime;
float stepTime;
float highValue;
float lowValue;
float stepValueRise;
float stepValueFall;
int offset; //Number of steps
};
struct CycleValues tensiometer0 =
{
.riseTime = 2700,
.fallTime = 900,
.plateauTime = 0,
.stepTime = 30,
.highValue = 42,
.lowValue = -3,
.stepValueRise = tensiometer0.stepTime * (tensiometer0.highValue - tensiometer0.lowValue) / tensiometer0.riseTime,
.stepValueFall = tensiometer0.stepTime * (tensiometer0.lowValue - tensiometer0.highValue) / tensiometer0.fallTime,
.offset = 0
};
struct CycleValues tensiometer1 =
{
.riseTime = 1200,
.fallTime = 480,
.plateauTime = 60,
.stepTime = 30,
.highValue = 38,
.lowValue = 0,
.stepValueRise = tensiometer1.stepTime * (tensiometer1.highValue - tensiometer1.lowValue) / tensiometer1.riseTime,
.stepValueFall = tensiometer1.stepTime * (tensiometer1.lowValue - tensiometer1.highValue) / tensiometer1.fallTime,
.offset = 0
};
struct CycleValues tensiometers[2] = {tensiometer0, tensiometer1};
struct CycleValues tensiometer = tensiometers[current_tensiometer];
#pragma pack(push,1)
struct SmartSensorStruct {
char crc; ///< Checksum CRC8
char serial[11]; ///< No Série du capteur. Doit demeurer à l'offset 1 dans la structure
char gain; ///< Gain à appliquer
char sampling_rate; ///< Vitesse de sampling
char model; ///< Model de capteur
short c1; ///< Consigne c1 de calcul
short c2; ///< Consigne c2 de calcul
short c3; ///< Consigne c3 de calcul
char depth; ///< Profondeur du capteur en mètres ou en pieds
short c4; ///< Consigne c4 de calcul
unsigned long code;///< Code de détection du type de smartSensor (Salinité ou Tension)
}SmartSensorStruct_packed;
#pragma pack(pop)
struct SmartSensorStruct stSensor;
char RAMBuffer[256]; //simulate EEPROM
void DoCRC8(char* a_crc8, char b)
{
char i, j;
for (i = 0; i < 8; b >>= 1, i++) {
j = (b ^ (*a_crc8)) & 1;
(*a_crc8) >>= 1;
if (j) (*a_crc8) ^= 0x8C;
}
}
void setTension(double value)
{
int tensionset = (int)(value*100);
int adc = ((1000 * (tensionset - stSensor.c3)) / stSensor.c2) - stSensor.c1;
adc = adc / 4; //into low read of the ST
ADCValue[0] = (adc >> 8)&0xFF;
ADCValue[1] = (adc)&0xFF;
}
char ComputeCRC8(char *buff, char len, char start_data)
{
char crc8 = 0;
DoCRC8(&crc8, start_data);
while (len--) DoCRC8(&crc8, *buff++);
return crc8;
}
void SaveRamBuffer(char address, char* value, unsigned char length)
{
unsigned char i;
for(i = 0; i < length; i++)
RAMBuffer[address + i] = value[i];
}
void SaveData(char add, long value)
{
SaveRamBuffer(add, (char*)&value, 4);
}
void I2C_1Process()
{
char buf[MAX_WRITE_SIZE + 1];
int nbRx = 0;
for(int i = 0; i < MAX_WRITE_SIZE; i++) buf[i] = 0; // Clear buffer
int rx = slave.receive();
switch (rx)
{
case I2CSlave::ReadAddressed:
slave.write(&RAMBuffer[PointOnAddress], 0xFF - PointOnAddress);
break;
/*case I2CSlave::WriteGeneral:
break;*/
case I2CSlave::WriteAddressed:
int ret = slave.read(buf, 1);
PointOnAddress = buf[0];
nbRx = slave.getCount();
if (nbRx > 0) //to simulate write on EEPROM need to test
{
ret = slave.read(buf, nbRx);
SaveRamBuffer(PointOnAddress, buf, nbRx);
}
break;
}
}
void I2C_2Process()
{
char buf[MAX_WRITE_SIZE + 1];
int rx = slave2.receive();
int nbRx = 0;
switch (rx)
{
case I2CSlave::ReadAddressed:
slave2.write((char*)&ADCValue, 2);
break;
/*case I2CSlave::WriteGeneral:
break;*/
case I2CSlave::WriteAddressed:
//to empty read buffer we do nothing with the data
int ret = slave2.read(buf, 1);
nbRx = slave2.getCount();
if (nbRx > 0) //to simulate write on EEPROM need to test
{
ret = slave2.read(buf, nbRx);
}
break;
}
}
void I2CSlaveProcess()
{
I2C_1Process();
I2C_2Process();
}
void InitI2CSlaveComm()
{
slave.address(0xA0);
sprintf(stSensor.serial, "2059123456");
stSensor.gain = 0x01;
stSensor.sampling_rate = 0x03;
stSensor.c1 = -37;
stSensor.c2 = 634;
stSensor.c3 = -7;
stSensor.c4 = -1;
stSensor.depth = 0x00;
stSensor.model = 2; //Nombre de données à transmettre vers le ST
stSensor.code = 0xFFFF; //Type of sensor
stSensor.crc = ComputeCRC8(((char *)&stSensor)+1, sizeof(SmartSensorStruct_packed) - 7, 0);
SaveRamBuffer(0, (char*)&stSensor, sizeof(SmartSensorStruct_packed));
slave2.address(0x90);
}
void cycle()
{
if(modeSwitch == 3 )
{
if(saveSwitch == 2)
{
printf("Tension fall begins\n");
}
else if (saveSwitch == 1)
{
printf("Tension rise begins\n");
}
counter = 0;
modeSwitch = saveSwitch;
}
else
{
if(modeSwitch == 1)
{
printf("High plateau begins\n");
saveSwitch = 2;
modeSwitch = 3;
}
else if (modeSwitch == 2)
{
printf("Low plateau begins\n");
saveSwitch = 1;
modeSwitch = 3;
}
}
}
void commandselect()
{
if(PcUart.readable())
{
char command = PcUart.getc();
switch(command)
{
case 'w':
{
flow_ticker.detach();
printf("Setting parameters\n");
printf("Enter tension high value in kPa\n");
scanf("%s", buffer);
tensiometer.highValue = atoi(buffer);
printf("Enter tension low value in kPa\n");
scanf("%s", buffer);
tensiometer.lowValue = atoi(buffer);
printf("Enter tension rise time in seconds\n");
scanf("%s", buffer);
tensiometer.riseTime = atoi(buffer);
printf("Enter tension fall time in seconds\n");
scanf("%s", buffer);
tensiometer.fallTime = atoi(buffer);
printf("Enter plateau time in seconds\n");
scanf("%s", buffer);
tensiometer.plateauTime = atoi(buffer);
printf("Enter step time in seconds\n");
scanf("%s", buffer);
tensiometer.stepTime = atoi(buffer);
printf("Resetting cycle\n");
counter = 0;
tension = tensiometer.lowValue;
modeSwitch = 1;
flow_ticker.attach(&flow, tensiometer.stepTime);
break;
}
case 'i':
{
printf("List of parameter values\n");
printf("High tension: %d kPa\n", (int)tensiometer.highValue);
printf("Low tension: %d kPa\n", (int)tensiometer.lowValue);
printf("Cycle rise time: %d seconds\n", (int)tensiometer.riseTime);
printf("Cycle fall time: %d seconds\n", (int)tensiometer.fallTime);
printf("Cycle plateau time: %d seconds\n", (int)tensiometer.plateauTime);
printf("Step time: %d seconds\n", (int)tensiometer.stepTime);
if(modeSwitch == 1)
printf("Cycle currently in rising phase\n");
else if(modeSwitch == 2)
printf("Cycle currently in falling phase\n");
else if(modeSwitch == 3)
printf("Cycle currently in plateau phase\n");
break;
}
}
}
}
void flow()
{
if(modeSwitch == 3)
{
counter += tensiometer.stepTime;
if(counter >= tensiometer.plateauTime)
cycle();
}
else
{
if(modeSwitch == 1)
{
tension += tensiometer.stepValueRise;
printf("Rising, tension = %f\n", tension);
}
if(modeSwitch == 2)
{
tension += tensiometer.stepValueFall;
printf("Falling, tension = %f\n", tension);
}
setTension(tension);
if(modeSwitch == 1 && tension >= tensiometer.highValue - 0.001f)
{
tension = tensiometer.highValue;
cycle();
}
else if(modeSwitch == 2 && tension <= tensiometer.lowValue + 0.001f)
{
tension = tensiometer.lowValue;
cycle();
}
}
}
void setStartingValue()
{
int numberOfSteps = (tensiometer.riseTime + tensiometer.fallTime + (2 * tensiometer.plateauTime)) / tensiometer.stepTime;
printf("Total number of steps : %i\n", numberOfSteps);
printf("Lenght of cycle (seconds) : %f\n", numberOfSteps * tensiometer.stepTime);
int offset = tensiometer.offset % numberOfSteps;
printf("Offset after modulo : %i\n", offset);
if (offset * tensiometer.stepTime <= tensiometer.riseTime)
{
tension = tensiometer.lowValue + (tensiometer.offset * tensiometer.stepValueRise);
}
else if (offset * tensiometer.stepTime > tensiometer.riseTime && offset * tensiometer.stepTime <= (tensiometer.riseTime + tensiometer.plateauTime))
{
tension = tensiometer.highValue;
modeSwitch = 3;
}
else if (offset * tensiometer.stepTime > (tensiometer.riseTime + tensiometer.plateauTime) && offset * tensiometer.stepTime <= (tensiometer.riseTime + tensiometer.plateauTime + tensiometer.fallTime))
{
tension = tensiometer.highValue + (tensiometer.offset * tensiometer.stepValueFall);
modeSwitch = 2;
}
else
{
tension = tensiometer.lowValue;
modeSwitch = 3;
}
printf("Starting tension : %f\n", tension);
switch (modeSwitch)
{
case 1:
printf("Starting phase : rising\n");
break;
case 2:
printf("Starting phase : falling\n");
break;
case 3:
printf("Starting phase : plateau\n");
}
}
void resetCycle()
{
printf("Beginning simulation, tensiometer #%i\n", current_tensiometer);
modeSwitch = 1;
saveSwitch = 0;
counter = 0;
setStartingValue();
flow_ticker.attach(&flow, tensiometer.stepTime);
command_ticker.attach(&commandselect, 1);
}
int main()
{
/*
printf("Setting parameters\n");
printf("Enter tension high value in kPa\n");
scanf("%s", buffer);
highValue = atoi(buffer);
printf("Enter tension low value in kPa\n");
scanf("%s", buffer);
lowValue = atoi(buffer);
printf("Enter tension rise time in seconds\n");
scanf("%s", buffer);
riseTime = atoi(buffer);
printf("Enter tension fall time in seconds\n");
scanf("%s", buffer);
fallTime = atoi(buffer);
printf("Enter plateau time in seconds\n");
scanf("%s", buffer);
plateauTime = atoi(buffer);
printf("Enter step time *in milliseconds*\n");
scanf("%s", buffer);
stepTime = (float)atoi(buffer)/1000;
tension = lowValue;
stepValue = stepTime * (highValue - lowValue) / riseTime;
*/
InitI2CSlaveComm();
resetCycle();
while(1)
{
if (mybutton == 0) // Button is pressed
{
myled = !myled; // Toggle the LED state
wait(0.2); // 200 ms
}
if (!current_tensiometer == myled)
{
current_tensiometer = myled;
tensiometer = tensiometers[current_tensiometer];
resetCycle();
}
I2CSlaveProcess();
}
}