stm32duino / Arduino_Core_STM32

STM32 core support for Arduino
https://github.com/stm32duino/Arduino_Core_STM32/wiki
Other
2.81k stars 966 forks source link

STM32 Blue Pill (STM32F103C8) #2257

Closed WeiKangLim24 closed 9 months ago

WeiKangLim24 commented 9 months ago

Hardware: STM32 Blue Pill (STM32F103C8) Boot using STLINK V2 Board Manger: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_ The error: The "Timer1" was not declared in this scope

My code:

#include "Arduino.h"
#include "LMP91000.h"
#include <Wire.h>
#include <HardwareTimer.h>
#include <Adafruit_MCP4725.h>

#define VOUT PA0  // 36
#define WE PA1
#define RE PA2
#define LMPADDR 0x48
#define DACADDR 0x60
#define SECOND 1000     // how many ms in 1 second
#define MINUTE 60000    // how many ms in 1 minute
#define RTIA_DEFAULT 4  // 5

Adafruit_MCP4725 DAC;
LMP91000 pstat = LMP91000();

short fixedRTIA = 0;
short rtia = 5;
short rload = 0;
bool DPV_start = false;
bool SWV_start = false;
uint8_t RTIA = RTIA_DEFAULT;
uint32_t limit = 0;
float sampling_delay = 0.0;
unsigned long lastTime = 0;
float target_bias_prev = 0.0;
bool CV_start = false;
bool CA_start = false;
bool spike = false;
short CA_unit = 0;

//--user define start CV
short Vmax = 0;       // unit: mV
short Vmin = 0;       
short scan_rate = 0;  // unit: mV/s
short v_start = 0;    
short v_end = 0;
int technique = 0;
int step_increase = 0;  // resolution (mV)
int stop_crossing = 0;  // no. of times voltage crosses 0mV
bool Vdirection = true;
//--user define end

//--user define start CA
short sampling_rate = 0; // Hz
short v_step = 0;
short t_start = 0;         
unsigned long t_step = 0;
short t_end = 0;         
//--user define end

short v_end_2 = 0;
short Estep = 0;
short Epulse = 0;
short Pwidth = 0;
short Period = 0;
short Tquiet = 0;
short Trelax = 0;

//CV
short target_bias = 0;
int dac = 0;
double vout = 0;
double tmp = 0.000;
double Vcheck = 0.00;
int stop_crossing_index = 0;
float percentage = 0.0;
uint32_t interruptCounter = 0;
uint32_t interruptCounter_prev = 0;

//--Reset after completion
bool getTechnique = false;
bool getParams = false;

//CA
int timer_divider = 0;
bool complete = false;

void VariableReset() {
  Vmax = 0;       // unit: mV
  Vmin = 0;       
  scan_rate = 0;  // unit: mV/s
  v_start = 0;    
  v_end = 0;      
  technique = 0;
  step_increase = 0;  // resolution (mV)
  stop_crossing = 0;  
  Vdirection = true;
  sampling_rate = 0;
  v_step = 0;
  t_start = 0;  //ms
  t_step = 0;   //ms
  t_end = 0;    //ms
  v_end_2 = 0;
  Estep = 0;
  Epulse = 0;
  Pwidth = 0;
  Period = 0;
  Tquiet = 0;
  Trelax = 0;
  target_bias = 0.0;
  dac = 0;
  vout = 0;
  tmp = 0.000;
  Vcheck = 0.00;
  stop_crossing_index = 0;
  percentage = 0.0;
  interruptCounter = 0;
  interruptCounter_prev = 0;
  timer_divider = 0;
  complete = false;
  sampling_delay = 0.0;
  target_bias_prev = 0.0;
  CV_start = false;
  CA_start = false;
  DPV_start = false;
  SWV_start = false;
  spike = false;
  RTIA = RTIA_DEFAULT;  
  limit = 0;
  Wire.beginTransmission(0x48);
  pstat.standby();
  pstat.disableFET();
  pstat.setRLoad(rload);  //0
  pstat.setRefSource(1);
  pstat.setBias(9);     //5 -- 8 // 3
  pstat.setGain(rtia);  // TIA GAIN
  pstat.setIntZ(1);     //
  pstat.setPosBias();
  pstat.setThreeLead();
  Wire.endTransmission();
  delay(2000);  //warm-up time for gas sensor
}

void onTimer() {
  interruptCounter++;
}

// applyBias sets Pos/Neg bias, DAC value, and the percentage
void applyBias2(float target_bias) {
  float percentage = 0.0;
  int LMP_percentage = 0;
  if (abs(target_bias) <= 793.0 && abs(target_bias) >= 726.0) {
    LMP_percentage = 13;
    percentage = 0.24;
  } else if (abs(target_bias) <= 726.0 && abs(target_bias) >= 660.0) {
    LMP_percentage = 12;
    percentage = 0.22;
  } else if (abs(target_bias) <= 660.0 && abs(target_bias) >= 594.0) {
    LMP_percentage = 11;
    percentage = 0.2;
  } else if (abs(target_bias) <= 594.0 && abs(target_bias) >= 528.0) {
    LMP_percentage = 10;
    percentage = 0.18;
  } else if (abs(target_bias) <= 528.0 && abs(target_bias) >= 462.0) {
    LMP_percentage = 9;
    percentage = 0.16;
  } else if (abs(target_bias) <= 462.0 && abs(target_bias) >= 396.0) {
    LMP_percentage = 8;
    percentage = 0.14;
  } else if (abs(target_bias) <= 396.0 && abs(target_bias) >= 330.0) {
    LMP_percentage = 7;
    percentage = 0.12;
  } else if (abs(target_bias) <= 330.0 && abs(target_bias) >= 264.0) {
    LMP_percentage = 6;
    percentage = 0.10;
  } else if (abs(target_bias) <= 264.0 && abs(target_bias) >= 198.0) {
    LMP_percentage = 5;
    percentage = 0.08;
  } else if (abs(target_bias) <= 198.0 && abs(target_bias) >= 132.0) {
    LMP_percentage = 4;
    percentage = 0.06;
  } else if (abs(target_bias) <= 132.0 && abs(target_bias) >= 66.0) {
    LMP_percentage = 3;
    percentage = 0.04;
  } else if (abs(target_bias) <= 66.0 && abs(target_bias) >= 33.0) {
    LMP_percentage = 2;
    percentage = 0.02;
  } else if (abs(target_bias) <= 33.0 && abs(target_bias) >= 15.0) {
    LMP_percentage = 1;
    percentage = 0.01;
  } else {
    LMP_percentage = 0;
    percentage = 0.0;
  }

  if (target_bias >= 0) {
    Wire.beginTransmission(0x48);
    pstat.setPosBias();
    Wire.endTransmission();
  } else {
    Wire.beginTransmission(0x48);
    pstat.setNegBias();
    Wire.endTransmission();
  }
  if (abs(target_bias) < 15) {
    if (abs(target_bias) >= 7.5) {
      target_bias = 15;
    } else {       // less than 7.5mV ---> become 0
      dac = 1860;  // 1.5V
      Wire.beginTransmission(0x48); // LMP91000 address = 0x48
      pstat.setBias(0);
      Wire.endTransmission();
    }
  } else {
    dac = int((target_bias * 4096) / (1000 * percentage * 3.3));
  }
  Wire.beginTransmission(0x60);
  DAC.setVoltage(int(abs(dac)), false);
  Wire.endTransmission();

  // apply bias percentage at LMP
  Wire.beginTransmission(0x48);
  pstat.setBias(LMP_percentage);
  Wire.endTransmission();
}

uint16_t avgAnalogRead() {
  uint32_t sum = 0;
  uint32_t avgVOUT = 0;
  int samples = 5;
  for (int x = 0; x < samples; x++) {
    sum += analogRead(VOUT);
  }
  avgVOUT = (sum / samples) * 3.3 * 1000 / 4095;  //mV
  return avgVOUT;
}

double ReadCurrent(float target_bias, int dac) {
  spike = false;
  float tmp = 0.0;
  int avgV = avgAnalogRead();
  Wire.beginTransmission(0x48);
  float IntZ = pstat.getIntZ();
  float Gain = pstat.getGain();
  Wire.endTransmission();
  float v_intz = 1000 * IntZ * 3.3 * dac / 4095;
  if (fixedRTIA == 0){
    if (abs(target_bias) > 15) {  //try omit this?
      if ((avgV < 50) || (avgV > 3250)) {
        if (interruptCounter - limit > 5) {
          if (RTIA > 1) {
            RTIA -= 1;
            spike = true;
            limit = interruptCounter;
          }
        }
      } else if (abs(avgV - v_intz) < 50) {  //< 200 ){
        if (interruptCounter - limit > 5) {
          if (RTIA > 0 && RTIA < 7) {
            RTIA += 1;
            spike = true;
            limit = interruptCounter;
          } else if (RTIA == 0) {
            RTIA = 0;
          }
        }
      }
    }
  }
  else {
    RTIA = rtia;
  }
  if (RTIA == 0) {
    Wire.beginTransmission(0x48);
    pstat.setGain(RTIA);  // rtia
    Wire.endTransmission();
    tmp = 1000 * (avgV - 1000 * (abs(dac) * 3.3 / 4095) * IntZ) / 2000000;  //Gain;
  } else {
    Wire.beginTransmission(0x48);
    pstat.setGain(RTIA);
    IntZ = pstat.getIntZ();
    Wire.endTransmission();
    tmp = 1000 * (avgV - 1000 * (abs(dac) * 3.3 / 4095) * IntZ) / Gain;  //Gain;  
  }
  return tmp;  // in micro amps
}

void CV(short Vmax, short Vmin, short scan_rate, short v_start, short v_end, short step_increase, short stop_crossing, short target_bias, short timer_divider) {
  lastTime = millis();
  Timer1.setPeriod(1000 * timer_divider);  // in microseconds
  Timer1.resume();
  Timer1.attachInterrupt(TIMER_CH1, onTimer);
  delay(50);
  while (stop_crossing_index != stop_crossing) {
    if (Vdirection == true && stop_crossing_index != stop_crossing) {
      while (target_bias < Vmax) {
        digitalWrite(PC13, HIGH);
        delay(1);
        if (interruptCounter > interruptCounter_prev) {
          interruptCounter_prev = interruptCounter;
          target_bias_prev = target_bias;
          target_bias += step_increase;
          Vcheck = 1000 * analogRead(WE) / 4096 * 3.3 - 1000 * analogRead(RE) / 4096 * 3.3;
          tmp = ReadCurrent(target_bias_prev, dac);
          applyBias2(target_bias);
          if (CV_start == true && spike == false) {
            Serial.print(millis() - lastTime);
            Serial.print(",");
            Serial.print(target_bias_prev);
            Serial.print(",");
            Serial.print(tmp);
            Serial.print(",");
            Serial.print(Vcheck);
            Serial.print(",");
            Serial.println(avgAnalogRead());
          }
          if (target_bias == v_end) {
            stop_crossing_index++;
            if (stop_crossing_index == stop_crossing) {
              break;
            }
          }
          CV_start = true;
        }
      }
    }
    Vdirection = false;
    if (Vdirection == false && stop_crossing_index != stop_crossing) {
      while (target_bias > Vmin) {
        delay(1);
        if (interruptCounter > interruptCounter_prev) {
          interruptCounter_prev = interruptCounter;
          target_bias_prev = target_bias;
          target_bias -= step_increase;
          Vcheck = 1000 * analogRead(WE) / 4096 * 3.3 - 1000 * analogRead(RE) / 4096 * 3.3;
          tmp = ReadCurrent(target_bias_prev, dac);
          applyBias2(target_bias);
          if (CV_start == true && spike == false) {
            Serial.print(millis() - lastTime);
            Serial.print(",");
            Serial.print(target_bias_prev);
            Serial.print(",");
            Serial.print(tmp);
            Serial.print(",");
            Serial.print(Vcheck);
            Serial.print(",");
            Serial.println(avgAnalogRead());
          }
          if (target_bias == v_end) {
            stop_crossing_index++;
            if (stop_crossing_index == stop_crossing) {
              break;
            }
          }
          CV_start = true;
        }
      }
    }
    Vdirection = true;
    if (stop_crossing_index == stop_crossing) {
      Timer1.pause();
      break;
    }
  }
  Serial.println("complete");
  Timer1.pause();
}

void CA(short sampling_rate, short v_start, short v_step, short v_end, short t_start, unsigned long t_step, short t_end, short target_bias, short timer_divider) {
  lastTime = millis();
  Timer1.setPeriod(timer_divider * 1000);  // ISR period in microseconds
  Timer1.attachInterrupt(TIMER_CH1, onTimer);
  Timer1.resume();
  while (complete == false) {
    delay(1);
    if (interruptCounter > interruptCounter_prev) {
      interruptCounter_prev = interruptCounter;
      target_bias_prev = target_bias;
      tmp = ReadCurrent(target_bias, dac);
      if (interruptCounter == 1) {  // to prevent applying bias multiple times (apply bias once only)
        target_bias = v_start;
        applyBias2(target_bias);
      } else if (interruptCounter == t_start * sampling_rate / 1000 + 1) {
        target_bias = v_step;
        applyBias2(target_bias);
      } else if (interruptCounter == (t_start + t_step) * sampling_rate / 1000 + 1) {
        target_bias = v_end;
        applyBias2(target_bias);
      } else if (interruptCounter == (t_start + t_step + t_end) * sampling_rate / 1000 + 1) {
        complete = true;
      }
      Vcheck = 1000 * analogRead(WE) / 4096 * 3.3 - 1000 * analogRead(RE) / 4096 * 3.3;
      if (CA_start == true && spike == false) {
        Serial.print(millis() - lastTime);
        Serial.print(",");
        Serial.print(target_bias_prev);
        Serial.print(",");
        Serial.print(tmp);
        Serial.print(",");
        Serial.println(Vcheck);
      }
      CA_start = true;
    }
  }
  complete = false;
  Serial.println("complete");
  Timer1.pause();
}

void DPV(short sampling_rate, short v_start, short v_end, short v_end_2, short Estep, short Epulse, short Pwidth, short Period, short Tquiet, short Trelax, short target_bias, short timer_divider) {
  bool dpv_done = false;
  lastTime = millis();
  Timer1.setPeriod(timer_divider * 1000);  // ISR period in microseconds
  Timer1.attachInterrupt(TIMER_CH1, onTimer);
  Timer1.resume();
  int ctr = 0;
  float i1 = 0.0;
  float i2 = 0.0;
  short target_bias_plot = 0;
  while (dpv_done == false) {
    delay(1);
    if (interruptCounter > interruptCounter_prev) {
      interruptCounter_prev = interruptCounter;
      ctr++;
      if (DPV_start == false) {  // 1st cycle
        target_bias -= Epulse;
        applyBias2(target_bias);  //, findPercentage(target_bias));
        DPV_start = true;
      } else if (ctr == Pwidth * sampling_rate / 1000 + 1) {  // completed "ON" time
        if (v_end < v_start) {
          if (target_bias + (Epulse - Estep) <= v_end) {  // last pulse
            i1 = ReadCurrent(target_bias, dac);
            target_bias_plot = target_bias;
            target_bias = v_end;
            applyBias2(target_bias);
            dpv_done = true;
          } else {  // not last pulse
            i1 = ReadCurrent(target_bias, dac);
            target_bias_plot = target_bias;
            target_bias = target_bias + (Epulse - Estep);
            applyBias2(target_bias);
          }
        } else {
          if (target_bias + Epulse - Estep <= v_end) {  // last pulse
            i1 = ReadCurrent(target_bias, dac);
            target_bias_plot = target_bias;
            target_bias = v_end;
            dpv_done = true;
            applyBias2(target_bias);  //, findPercentage(target_bias));
          } else {                    // not last pulse
            i1 = ReadCurrent(target_bias, dac);
            target_bias_plot = target_bias;
            target_bias = target_bias - (Epulse - Estep);
            applyBias2(target_bias);  //, findPercentage(target_bias));
          }
        }
      } else if (ctr == Period * sampling_rate / 1000 + 1) {  // completed full period
        i2 = ReadCurrent(target_bias, dac);
        target_bias_plot = target_bias;
        target_bias -= Epulse;
        applyBias2(target_bias);  //, findPercentage(target_bias));
        if (DPV_start == true) {  //&& spike == false && abs(target_bias) > 15){
          Serial.print(millis() - lastTime);
          Serial.print(",");
          Serial.print(target_bias_plot);
          Serial.print(",");
          Serial.print(i2 - i1);
          Serial.print(",");
          Serial.println(target_bias_plot);
        }
        ctr = 0;
      }
    }
  }
  Serial.println("complete");
  Timer1.pause();
}

void SWV(short sampling_rate, short v_start, short v_end, short Estep, short Epulse, short Period, short Tquiet, short Trelax, short target_bias, short timer_divider) {
  bool swv_done = false;
  lastTime = millis();
  applyBias2(target_bias);
  delay(Tquiet);
  Timer1.setPeriod(timer_divider * 1000);  // ISR period in microseconds
  Timer1.attachInterrupt(TIMER_CH1, onTimer);
  Timer1.resume();
  int ctr = 0;
  float i1 = 0.0;
  float i2 = 0.0;
  short target_bias_plot = 0;

  while (swv_done == false) {
    delay(1);
    if (interruptCounter > interruptCounter_prev) {
      interruptCounter_prev = interruptCounter;
      ctr++;
      // Serial.println("what");
      if (SWV_start == false) {
        target_bias += Epulse;
        applyBias2(target_bias);
        SWV_start = true;
      } else {
        if (v_start < v_end) {
          if (target_bias + Epulse <= v_end) {
            if (ctr == (Period * sampling_rate) / (2 * 1000) + 1) {  // half a period
              i1 = ReadCurrent(target_bias, dac);
              target_bias_plot = target_bias;
              target_bias -= 2 * Epulse;
              applyBias2(target_bias);
            }
            if (ctr == (Period * sampling_rate) / (1000) + 1) {  //end of period
              i2 = ReadCurrent(target_bias, dac);
              target_bias += 2 * Epulse + Estep;
              applyBias2(target_bias);
              ctr = 0;
              if (SWV_start == false) {
                Serial.print(millis() - lastTime);
                Serial.print(",");
                Serial.print(target_bias);
                Serial.print(",");
                Serial.print(i2 - i1);
                Serial.print(",");
                Serial.println(target_bias_plot);
              }
            }
          } else {
            Serial.println("complete");
            Timer1.pause();
            swv_done = true;
            break;
          }
          if (target_bias >= v_end) {
            Serial.print("complete");
            swv_done = true;
          }
        } else {
          if (target_bias + Epulse >= v_end) {
            if (ctr == (Period * sampling_rate) / (2 * 1000) + 1) {  // half a period
              i1 = ReadCurrent(target_bias, dac);
              target_bias_plot = target_bias;
              target_bias -= (2 * Epulse + Estep);
              applyBias2(target_bias);
            }
            if (ctr == (Period * sampling_rate) / (1000) + 1) {  //end of period
              i2 = ReadCurrent(target_bias, dac);
              target_bias += (2 * Epulse);
              applyBias2(target_bias);
              ctr = 0;
              if (SWV_start == true && spike == false) {
                Serial.print(millis() - lastTime);
                Serial.print(",");
                Serial.print(target_bias);
                Serial.print(",");
                Serial.print(i1 - i2);
                Serial.print(",");
                Serial.println(target_bias_plot);
              }
            }
          } else {
            Serial.println("complete");
            Timer1.pause();
            swv_done = true;
            break;
          }
          if (target_bias <= v_end) {
            Serial.print("complete");
            swv_done = true;
          }
        }
      }
    }
  }
}

void setup()
{
  pinMode(PC13, OUTPUT);
  pinMode(PA0, INPUT);
  pinMode(PA1, INPUT);
  pinMode(PA2, INPUT);

  pinMode(PA5, OUTPUT);
  digitalWrite(PA5,LOW);

  analogReadResolution(12);

  Serial.begin(9600);
  while (!Serial) {
    delay(1);//won't run code until serial monitor is open
  }

  Wire.setSDA(PB9);
  Wire.setSCL(PB8);

  Wire.begin();
  DAC.begin(0x60); //I have my ADDR pin connected to GND so address is 0x60
  delay(50);
  Wire.beginTransmission(0x48);
  pstat.standby();
  pstat.disableFET();
  pstat.setRLoad(0); //11=100ohm; 0=10ohm 
  pstat.setRefSource(1);
  pstat.setBias(9);
  pstat.setGain(RTIA_DEFAULT); //chnage your gain as necessary. Bigger number higher gain. Lower number, lower gain.
  pstat.setIntZ(1);
  pstat.setPosBias();
  pstat.setThreeLead();
  Wire.endTransmission();
  delay(3000); //warm-up time for the gas sensor

}

void loop()
{
  digitalWrite(PC13, LOW);
}
fpistm commented 9 months ago

Hi @WeiKangLim24 As you didn't instantiate Timer1 this is normal. Usage: https://github.com/stm32duino/Arduino_Core_STM32/wiki/HardwareTimer-library

You shoud have something like that in your code: HardwareTimer *Timer1 = new HardwareTimer(TIM1); or HardwareTimer Timer1(TIM1);

And Please avoid to open an issue for such kind of problem. Use discussion or the forum.