Hortau / Mbed 2 deprecated Tensiometer_Simulator_waterbench

Dependencies:   mbed

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();
    }
}