(SKU: DFR0504)模拟量隔离模块

来自DFRobot Product Wiki
跳转至: 导航搜索
模拟量隔离模块

目录

简介

不少场合,需要电气隔离,才能保证传感器模块的可靠运行。例如有些传感器,比如ph传感器与电导率传感器,如果共用一个电源,就会相互干扰,不能正常工作。为保证传感器模块稳定可靠的运行,常用方案是把信号与电源都隔离起来。目前有现成的数字量隔离芯片方案,但还没有简单易用、arduino兼容的模拟量隔离模块。
为此,我们推出了一款arduino兼容的模拟量隔离模块,能够隔离模拟信号,有效防止传感器之间的相互干扰。该模块板载5V隔离电源,可直接提供给传感器模块使用,无需额外的电源,简单实用。连线接口专为DFRobot 3Pin模拟传感器设计,即插即用,无需焊接。模拟量变送比为1:1,即两端模拟量的大小始终保持一致,因此把该模块串到电路中后,基本不会影响传感器输出的模拟量,所以主控板上的采集模拟量的代码无需更改,简单方便。
使用这款模拟量隔离模块,可轻松解决传感器之间的相互干扰。如用于多合一水质检测系统,不用担心水质传感器之间相互干扰。
本产品几乎兼容DFRobot所有的模拟输出型传感器,加上DFRobot具有种类丰富的传感器,因此本产品可用于多种需要隔离的应用场合,满足您的多种需求。

Warning yellow.png

1.本模块的MCU端(非隔离端),尽量提供5.0±0.1V的精确电压。输入电压精度越高,输出模拟量精度越高。
2.本模块工作时消耗电流较大,因此建议arduino主控板外接电源,以提供足够的电源功率,也能保证电源电压精度,不至于电源电压明显降低。
3.SEN端(隔离端)最大输出电流不得超过170mA,请注意负载的工作电流!
4.MCU端(非隔离端)的GND与SEN端(隔离端)的GND是相互隔离的,严禁将其短接!
5.工作过程中,隔离电源模块会发热,属正常现象。


技术规格

  • 工作电压:5.0V
  • 响应时间:4秒(typ)
  • 两端模拟量误差:<±20mV(typ)
  • 接口类型:PH2.0-3P
  • 空载电流:75mA(typ)
  • 产品尺寸:42*32mm
  • 非隔离端(接主控板)
    • 供电电压:5.0±0.1V
    • 模拟输出:0~5.0V
  • 隔离端(接传感器)
    • 输出电压:5.0±0.2V
    • 模拟输入:0~5.0V


引脚说明

模拟量隔离模块
模拟量隔离模块管脚定义
标号 名称 功能描述
1 A 模拟信号输出端(0~5.0V)
2 + 电源输入正极(5±0.1V)
3 - 电源输入负极
4 - 隔离电源输出负极
5 + 隔离电源输出正极(5.0±0.2V)
6 A 模拟输入端(0~5.0V)


接口说明

如下图所示,这款模拟量隔离模块有左边和右边两个接口。
左边接口,名称为SEN,和传感器模块连接; 右边接口,名称为MCU,和arduino主控板连接。

模拟量隔离模块


使用教程

本教程以电导率传感器为例,演示如何使用这个模拟量隔离模块对传感器模块进行隔离。
电导率传感器会向液体里释放高频信号,因此,如果同一溶液里还有其他水质传感器,如ph传感器,就会受到严重干扰。因此需要将这个电导率传感器隔离。

准备

  • 硬件
    • 1 x Arduino UNO控制板(或类似的主控板)
    • 1 x 传感器模块(本教程以电导率传感器模块为例)
    • 1 x PH2.0-3P模拟线
    • 1 x 双头PH2.0排线
    • 1 x 模拟量隔离模块
  • 软件
    • Arduino IDE (推荐使用传感器模块兼容的arduino IDE,模拟量隔离模块无需烧录代码), 点击下载Arduino IDE


接线图

如下图所示,将传感器模块连接到隔离模块的SEN端(实际连接时请使用双头PH2.0排线)。然后将隔离模块的MCU端连接到arduino主控板(实际连接时请使用传感器模拟线)

Isolation application2.png


样例代码

点击下载库文件OneWire
如何安装库?

/***************************************************
 DFRobot Gravity:Analog Electrical Conductivity Sensor
 <https://www.dfrobot.com/wiki/index.php/Analog_EC_Meter_SKU:DFR0300>
 ***************************************************
 This sample code reads the EC value.
 
 Created 2016-12-15
 By Jason <jason.ling@dfrobot.com@dfrobot.com>
 
 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/
#include <OneWire.h>
#include <EEPROM.h>
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

#define ReceivedBufferLength 20
char receivedBuffer[ReceivedBufferLength+1];   // store the serial command
byte receivedBufferIndex = 0;

#define ecSensorPin  A1  //EC Meter analog output,pin on analog 1
#define ds18b20Pin  2    //DS18B20 signal, pin on digital 2

#define SCOUNT  100           // sum of sample point
int analogBuffer[SCOUNT];    //store the analog value read from ADC
int analogBufferIndex = 0;

#define compensationFactorAddress 8    //the address of the factor stored in the EEPROM
float compensationFactor;

#define VREF 5000  //for arduino uno, the ADC reference is the power(AVCC), that is 5000mV

boolean enterCalibrationFlag = 0;
float temperature,ECvalue,ECvalueRaw;

OneWire ds(ds18b20Pin);

void setup()
{
    Serial.begin(115200);
    readCharacteristicValues(); //read the compensationFactor
}

void loop()
{
  
  if(serialDataAvailable() > 0)
  {
      byte modeIndex = uartParse();
      ecCalibration(modeIndex);    // If the correct calibration command is received, the calibration function should be called.
  }

   static unsigned long analogSampleTimepoint = millis();
   if(millis()-analogSampleTimepoint > 30U) //every 30ms,read the analog value from the ADC
   {
     analogSampleTimepoint = millis();
     analogBuffer[analogBufferIndex] = analogRead(ecSensorPin);    //read the analog value and store into the buffer,every 40ms
     analogBufferIndex++;
     if(analogBufferIndex == SCOUNT) 
         analogBufferIndex = 0;
   }
   
   static unsigned long tempSampleTimepoint = millis();
   if(millis()-tempSampleTimepoint > 850U)  // every 1.7s, read the temperature from DS18B20
   {
      tempSampleTimepoint=millis();
      temperature = readTemperature();  // read the current temperature from the  DS18B20
   }
   
   static unsigned long printTimepoint = millis();
   if(millis()-printTimepoint > 1000U)
   {
      printTimepoint = millis();
      float AnalogAverage = getMedianNum(analogBuffer,SCOUNT);   // read the stable value by the median filtering algorithm
      float averageVoltage=AnalogAverage*(float)VREF/1024.0;
      if(temperature == -1000)
      {
          temperature = 25.0;      //when no temperature sensor ,temperature should be 25^C default
          Serial.print(temperature,1); 
          Serial.print(F("^C(default)    EC:"));
      }else{
          Serial.print(temperature,1);    //current temperature
          Serial.print(F("^C             EC:"));
      }
     float TempCoefficient=1.0+0.0185*(temperature-25.0);    //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.0185*(fTP-25.0));
     float CoefficientVolatge=(float)averageVoltage/TempCoefficient;   
     if(CoefficientVolatge<150)Serial.println(F("No solution!"));   //25^C 1413us/cm<-->about 216mv  if the voltage(compensate)<150,that is <1ms/cm,out of the range
     else if(CoefficientVolatge>3300)Serial.println(F("Out of the range!"));  //>20ms/cm,out of the range
     else{ 
      if(CoefficientVolatge<=448)ECvalue=6.84*CoefficientVolatge-64.32;   //1ms/cm<EC<=3ms/cm
      else if(CoefficientVolatge<=1457)ECvalue=6.98*CoefficientVolatge-127;  //3ms/cm<EC<=10ms/cm
      else ECvalue=5.3*CoefficientVolatge+2278;                           //10ms/cm<EC<20ms/cm
      ECvalueRaw = ECvalue/1000.0;
      ECvalue = ECvalue/compensationFactor/1000.0;    //after compensation,convert us/cm to ms/cm
      Serial.print(ECvalue,2);     //two decimal
      Serial.print(F("ms/cm"));
       if(enterCalibrationFlag)             // in calibration mode, print the voltage to user, to watch the stability of voltage
       {  
          Serial.print(F("            Factor:"));
          Serial.print(compensationFactor);   
       }
     Serial.println();
     }          
   }   
}

boolean serialDataAvailable(void)
{
  char receivedChar;
  static unsigned long receivedTimeOut = millis();
  while (Serial.available()>0) 
  {   
    if (millis() - receivedTimeOut > 500U) 
    {
      receivedBufferIndex = 0;
      memset(receivedBuffer,0,(ReceivedBufferLength+1));
    }
    receivedTimeOut = millis();
    receivedChar = Serial.read();
    if (receivedChar == '\n' || receivedBufferIndex==ReceivedBufferLength){
		receivedBufferIndex = 0;
		strupr(receivedBuffer);
		return true;
    }else{
      receivedBuffer[receivedBufferIndex] = receivedChar;
      receivedBufferIndex++;
    }
  }
  return false;
}

byte uartParse()
{
  byte modeIndex = 0;
  if(strstr(receivedBuffer, "CALIBRATION") != NULL) 
      modeIndex = 1;
  else if(strstr(receivedBuffer, "EXIT") != NULL) 
      modeIndex = 3;
  else if(strstr(receivedBuffer, "CONFIRM") != NULL)   
      modeIndex = 2;
  return modeIndex;
}

void ecCalibration(byte mode)
{
    char *receivedBufferPtr;
    static boolean ecCalibrationFinish = 0;
    float factorTemp;
    switch(mode)
    {
      case 0:
      if(enterCalibrationFlag)
         Serial.println(F("Command Error"));
      break;
      
      case 1:
      enterCalibrationFlag = 1;
      ecCalibrationFinish = 0;
      Serial.println();
      Serial.println(F(">>>Enter Calibration Mode<<<"));
      Serial.println(F(">>>Please put the probe into the 12.88ms/cm buffer solution<<<"));
      Serial.println();
      break;
     
     case 2:
      if(enterCalibrationFlag)
      {
          factorTemp = ECvalueRaw / 12.88;
          if((factorTemp>0.85) && (factorTemp<1.15))
          {
              Serial.println();
              Serial.println(F(">>>Confrim Successful<<<"));
              Serial.println();
              compensationFactor =  factorTemp;
              ecCalibrationFinish = 1;
          }
          else{
            Serial.println();
            Serial.println(F(">>>Confirm Failed,Try Again<<<"));
            Serial.println();
            ecCalibrationFinish = 0;
          }        
      }
      break;

        case 3:
        if(enterCalibrationFlag)
        {
            Serial.println();
            if(ecCalibrationFinish)
            {
               EEPROM_write(compensationFactorAddress, compensationFactor);
               Serial.print(F(">>>Calibration Successful"));
            }
            else Serial.print(F(">>>Calibration Failed"));       
            Serial.println(F(",Exit Calibration Mode<<<"));
            Serial.println();
            ecCalibrationFinish = 0;
            enterCalibrationFlag = 0;
        }
        break;
    }
}

int getMedianNum(int bArray[], int iFilterLen) 
{
      int bTab[iFilterLen];
      for (byte i = 0; i<iFilterLen; i++)
      {
	  bTab[i] = bArray[i];
      }
      int i, j, bTemp;
      for (j = 0; j < iFilterLen - 1; j++) 
      {
	  for (i = 0; i < iFilterLen - j - 1; i++) 
          {
	    if (bTab[i] > bTab[i + 1]) 
            {
		bTemp = bTab[i];
	        bTab[i] = bTab[i + 1];
		bTab[i + 1] = bTemp;
	     }
	  }
      }
      if ((iFilterLen & 1) > 0)
	bTemp = bTab[(iFilterLen - 1) / 2];
      else
	bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
      return bTemp;
}

void readCharacteristicValues()
{
    EEPROM_read(compensationFactorAddress, compensationFactor);  
    if(EEPROM.read(compensationFactorAddress)==0xFF && EEPROM.read(compensationFactorAddress+1)==0xFF && EEPROM.read(compensationFactorAddress+2)==0xFF && EEPROM.read(compensationFactorAddress+3)==0xFF)
    {
      compensationFactor = 1.0;   // If the EEPROM is new, the compensationFactorAddress is 1.0(default).
      EEPROM_write(compensationFactorAddress, compensationFactor);
    }
}

//returns the temperature from one DS18B20 in DEG Celsius
float readTemperature()
{
  static byte data[12],addr[8];
  static float TemperatureSum = 25;
  static boolean ch = 0;
  if(!ch){
          if ( !ds.search(addr)) {
             // Serial.println("no more sensors on chain, reset search!");
              ds.reset_search();
              return -1000;
          }      
          if ( OneWire::crc8( addr, 7) != addr[7]) {
            //  Serial.println("CRC is not valid!");
              return -1000;
          }        
          if ( addr[0] != 0x10 && addr[0] != 0x28) {
            //  Serial.print("Device is not recognized!");
              return -1000;
          }      
          ds.reset();
          ds.select(addr);
          ds.write(0x44,1); // start conversion, with parasite power on at the end
  }else{  
          byte present = ds.reset();
          ds.select(addr);    
          ds.write(0xBE); // Read Scratchpad            
          for (int i = 0; i < 9; i++) { // we need 9 bytes
            data[i] = ds.read();
          }         
          ds.reset_search();           
          byte MSB = data[1];
          byte LSB = data[0];        
          float tempRead = ((MSB << 8) | LSB); //using two's compliment
          TemperatureSum = tempRead / 16;
    }
          ch = !ch;
          return TemperatureSum;  
}                       


结果

上传样例代码后,打开串口监视器,即可看到数值。
将模块以上述的连线方式串入到电路中,就起到了隔离的效果。

Isolation demo.png


常见问题

还没有客户对此产品有任何问题,欢迎通过qq或者论坛联系我们!


更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。


更多


DFshopping car1.png DFRobot商城购买链接

个人工具
名字空间

变换
操作
导航
工具箱