티스토리 뷰

SWDesk/Firmware

Arduino Library for MCP3426

inhae 2021. 6. 12. 11:47

Circuit Name : BMM215

 

<VIAcquisitor_MCP3426.h>

#ifndef VIAQ_MCP3426_H
#define VIAQ_MCP3426_H

#include "arduino.h"
#include <Wire.h>

class VIAcquisitor_MCP3426
{
  private:
    byte Address;
    byte Value_Configuration[2];
    char ChannelTypes[2];
    double ActualValues[2];
    double Value_Slope[2];
    double ReferenceValues[2];
    double UpperLimits[2];
    double LowerLimits[2];
    int SelectedChannelNo = 1;
    long StartTime_Device = -100;
    long StartTime_Conf = 0;
    double Value_LSB = -1.; // [mV]
    double MeasuredVoltage;
    boolean IsConnected = false;
    long MeasuringPeriod = 0;
    long Time_NextMeasurement = 0;
    int AlarmingCount = 0;
    int AlarmingNumberLimit = 10;
    
  public:
    VIAcquisitor_MCP3426();
    //~VIAcquisitor_MCP3426();
    void SetChannelConfiguration(byte portConf=0);
    int MeasureVoltage(boolean isUpdatable=false);
    double SetReferenceValue();
    double GetValue();
    String GetValueString();
    long GetElapsedTime();
    int GetChannelNo();
    void SetValue_LSB(double valueLSB);
    void ResetStartTime();
    double SetReferenceValue(int channelNo=0);
    void SetSlope(int channelNo, double slopeValue);
    void SetAddress(byte deviceAddress);
    void SetMeasuringPeriod(int period_Seconds);
    void SetUpperLimit(int channelNo, double upperLimit);
    void SetLowerLimit(int channelNo, double lowerLimit);
    void SetAlarmingNumber(int alarmNumber);
    void SetChannelType(int channelNo, char channelType);
    void SetNextMeasurement();
    String GetDeviceProperty(int portNo);
    int CheckDevice();
};

#endif

<VIAcquisitor_MCP3426.cpp>

#include "VIAcquisitor_MCP3426.h"

#define INTERVAL_CONF 100
#define VALUE_NONE (-999)
#define DEVICE_NONE (-10)
#define VALUE_NOTREADY 90
#define VALUE_UPDATE 100
#define VALUE_NOW 120
#define VALUE_PERIOD 200
#define VALUE_ALARM_L 410
#define VALUE_ALARM_U 420
#define VALUE_SIGNED 210 // sign changed
#define DEVICE_OK 1

#define ADDRESS_MCP3426A0 0X68
#define ADDRESS_MCP3426A1 0X69
#define ADDRESS_MCP3426A2 0X6A
#define ADDRESS_MCP3426A3 0X6B
#define CONF_MCP3426_CH1x8 0X1B // Channel#1, 16bit, X8
#define CONF_MCP3426_CH1x1 0X18 // Channel#1, 16bit, X1
#define CONF_MCP3426_CH2x8 0X3B // Channel#2, 16bit, X8
#define CONF_MCP3426_CH2x1 0X38 // Channel#2, 16bit, X1

VIAcquisitor_MCP3426::VIAcquisitor_MCP3426(){
  Value_Configuration[0] = CONF_MCP3426_CH1x1;
  Value_Configuration[1] = CONF_MCP3426_CH2x1;
  Value_Slope[0] = (1000./49.9); // for V_max of 40V
  Value_Slope[1] = (1000./402.); // for I_max of 2A
  ChannelTypes[0] = 'V';
  ChannelTypes[1] = 'I';
  UpperLimits[0] = 99999.0; 
  LowerLimits[0] = -99999.0;
  UpperLimits[1] = 99999.0; 
  LowerLimits[1] = -99999.0; 
  
  Address = ADDRESS_MCP3426A0;
  Value_LSB = 62.5/1000.; //[mV], actually [uV] 
  MeasuringPeriod = 0; // -1 ++++++++++++++++++++++++
  StartTime_Device = millis();
}

void VIAcquisitor_MCP3426::SetChannelConfiguration(byte channelConf=0){
  Wire.beginTransmission(Address);
  switch(channelConf){
    case 0:
      SelectedChannelNo++;
      if(SelectedChannelNo > 2) SelectedChannelNo = 1;
      Wire.write(CONF_MCP3426_CH1x1);
      break;
    case 1:
      SelectedChannelNo = 1;
      Wire.write(CONF_MCP3426_CH1x1);
      break;
    case 2:
      SelectedChannelNo = 2;
      Wire.write(CONF_MCP3426_CH2x1);
      break;
    default:
      SelectedChannelNo = 0;
      Wire.write(channelConf);
      break;
  }
  Wire.endTransmission();
  StartTime_Conf = millis();
}

int VIAcquisitor_MCP3426::MeasureVoltage(boolean isUpdatable=false){
  if((millis()-StartTime_Conf) < INTERVAL_CONF) return VALUE_NOTREADY;
  if(MeasuringPeriod < 0) return VALUE_NONE;

  Wire.beginTransmission((uint8_t)Address);
  Wire.requestFrom((uint8_t)Address, (uint8_t)3);
  if(Wire.available()){
    byte Byte3, Byte2, Byte1;
    Byte3 = Wire.read();
    Byte2 = Wire.read();
    Byte1 = Wire.read();
    int ADCValue = 0;
    ADCValue = (ADCValue|Byte3)<<8;
    ADCValue = (ADCValue|Byte2);
    MeasuredVoltage = double(ADCValue)*Value_LSB/1000.; //[mV]
    int channelIndex = SelectedChannelNo-1;
    double previousValue = ActualValues[channelIndex];
    double valueSlope = Value_Slope[channelIndex];
    double actualValue = valueSlope*MeasuredVoltage;
    if(ChannelTypes[channelIndex]=='I'){
      ActualValues[channelIndex] = actualValue - ReferenceValues[channelIndex]; // [mA]
      if(abs(ActualValues[channelIndex]) > 1.){ // over 1 mA
        if((previousValue*ActualValues[channelIndex]) < 0) return VALUE_SIGNED;
      }
    }else{
      ActualValues[channelIndex] = actualValue/1000.;
    }
    if(ActualValues[channelIndex] > UpperLimits[channelIndex]){
      if(AlarmingCount < AlarmingNumberLimit){
        AlarmingCount += 1;
        return VALUE_ALARM_U;
      }
    }else if(ActualValues[channelIndex] < LowerLimits[channelIndex]){
      if(AlarmingCount < AlarmingNumberLimit){
        AlarmingCount += 1;
        return VALUE_ALARM_L;
      }
    }else AlarmingCount = 0;
    if(MeasuringPeriod == 0) return VALUE_NOW;
    if(millis() > Time_NextMeasurement){
      if(isUpdatable) Time_NextMeasurement = millis() + MeasuringPeriod;
      return VALUE_PERIOD;
    }else return VALUE_UPDATE;
  }else{
    IsConnected = false;
    return DEVICE_NONE;  
  }
}

double VIAcquisitor_MCP3426::GetValue(){
  return ActualValues[SelectedChannelNo-1];
}

String VIAcquisitor_MCP3426::GetValueString(){
  String txString = String(1);
  txString += String(ChannelTypes[0]);
  txString += ":"; // Channel Type
  txString += String(ActualValues[0], 3);
  txString += ";";
  txString += String(2);
  txString += String(ChannelTypes[1]);
  txString += ":"; // Channel Type
  txString += String(ActualValues[1], 3);
  txString += ";";
  txString += String("ET:");
  txString += ":"; // Channel Type
  txString += String((millis() - StartTime_Device)/60/1000);
  return txString;  
}

double VIAcquisitor_MCP3426::SetReferenceValue(int channelNo=0){
  int channelIndex = -1;
  switch(channelNo){
    case 0:
      channelIndex = SelectedChannelNo-1;
      break;
    case 1:
      channelIndex = 0;
      break;
    case 2:
      channelIndex = 1;
      break;
      
  }
  ReferenceValues[channelIndex] = ActualValues[channelIndex];
  return MeasuredVoltage;
}

void VIAcquisitor_MCP3426::SetValue_LSB(double valueLSB){
  Value_LSB = valueLSB;
}

void VIAcquisitor_MCP3426::SetChannelType(int channelNo, char channelType){
  // channelType : 'V' or 'I'
  int channelIndex = channelNo-1;
  ChannelTypes[channelIndex] = channelType;
}

void VIAcquisitor_MCP3426::SetNextMeasurement(){
  Time_NextMeasurement = millis() + MeasuringPeriod;
}

int VIAcquisitor_MCP3426::CheckDevice(){
  Wire.beginTransmission((uint8_t)Address);
  Wire.requestFrom((uint8_t)Address, (uint8_t)3);
  if(Wire.available()){
    byte Byte3, Byte2, Byte1;
    Byte3 = Wire.read();
    Byte2 = Wire.read();
    Byte1 = Wire.read();
    return DEVICE_OK;
  }else return DEVICE_NONE;
}

String  VIAcquisitor_MCP3426::GetDeviceProperty(int portNo){
  String responseString = "";
  responseString = String(portNo);
  responseString += "P";
  responseString += ":";
  responseString += String(MeasuringPeriod);
  responseString += ";";
  responseString = String(portNo);
  responseString += "S";
  responseString += ":";
  responseString += String(Value_Slope[0], 3);

  return responseString;
}

void VIAcquisitor_MCP3426::SetAddress(byte deviceAddress){
  switch(deviceAddress){
    case 0:
    case 1:
    case 2:
    case 3:
      Address = ADDRESS_MCP3426A0 + deviceAddress;
      break;
    default:
      Address = deviceAddress;
      break;
  }
}

int VIAcquisitor_MCP3426::GetChannelNo(){return SelectedChannelNo;}
long VIAcquisitor_MCP3426::GetElapsedTime(){return (millis() - StartTime_Device);}
void VIAcquisitor_MCP3426::SetSlope(int channelNo, double slopeValue){Value_Slope[channelNo-1] = slopeValue;}
void VIAcquisitor_MCP3426::ResetStartTime(){StartTime_Device = millis();}
void VIAcquisitor_MCP3426::SetMeasuringPeriod(int period_Seconds){ MeasuringPeriod = long(period_Seconds)*1000;}
void VIAcquisitor_MCP3426::SetUpperLimit(int channelNo, double upperLimit){UpperLimits[channelNo-1] = upperLimit;}
void VIAcquisitor_MCP3426::SetLowerLimit(int channelNo, double lowerLimit){LowerLimits[channelNo-1] = lowerLimit;}
void VIAcquisitor_MCP3426::SetAlarmingNumber(int alarmNumber){AlarmingNumberLimit = alarmNumber;}

 

 

 

 

반응형
반응형
250x250
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함