정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

아두이노 , DO센서 + 수온센서 코딩합치기
양대 | 2018-09-20

안녕하세요 저희는 현재 DO센서 + 수온센서로 

 

용존산소농도 측정을 하려고 하는중인데

 

아두이노에서 컴파일 할때에

 

자꾸 오류가 나옵니다.

 

do 센서 컴파일시 정상 작동하며,

 

수온센서도 마찬가지로 정상 작동 합니다.

 

 

아래 코딩에서 어느 부분을 수정해야 정상적으로 2센서를 연결 할까요?

 

도움 부탁 드리겠습니다.

 

 

 

 

#include <avr/pgmspace.h>           //PROGMEM 메모리 필요 라이브러리

#include <EEPROM.h>          //아두이노 보드의 내장된 EEPROM 메모리사용 필요 라이브러리

#include <OneWire.h>                              //수온센서 코딩 필요 라이브러리

 

int DS18S20_Pin = 2;                               //DS18S20(수온센서) 2번 핀

OneWire ds(DS18S20_Pin);

void readDoCharacteristicValues(void);

int getMedianNum(int bArray[], int iFilterLen);

boolean serialDataAvailable(void);

byte uartParse();

void doCalibration(byte mode);

 

#define DoSensorPin  A1                //DO센서 핀을 A1에 연결

#define VREF 5000             //ADC(아두이노에서 아날로그 값을 디지털값으로 변환)참조 5V

float doValue;                        //읽어내려는 현재 용존 산소값 변수 정의

float temperature = 25;                   //현재의 온도를 25도 라고 설정

#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}                 //EEPROM에 write 할때 저장되는 주소 정의

#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}                 //EEPROM을 read 할때 사용하는 주소 정의

 

#define ReceivedBufferLength 20            //수신 버퍼 길이 20으로 정의

char receivedBuffer[ReceivedBufferLength+1];   

byte receivedBufferIndex = 0;

 

#define SCOUNT  30           // 샘플 포인트의 합

int analogBuffer[SCOUNT];    //ADC에서 읽은 배열에 아날로그값 저장

int analogBufferTemp[SCOUNT];

int analogBufferIndex = 0,copyIndex = 0;

 

#define SaturationDoVoltageAddress 12              //EEPROM에 저장된 포화 산소 전압

#define SaturationDoTemperatureAddress 16         //EEPROM에 저장된 포화 산소 온도의 주소

float SaturationDoVoltage,SaturationDoTemperature;

float averageVoltage;

 

 

 

 

const float SaturationValueTab[41] PROGMEM = {              //다양한 온도에서의 포화 용존산소농도 값

14.46, 14.22, 13.82, 13.44, 13.09,

12.74, 12.42, 12.11, 11.81, 11.53,

11.26, 11.01, 10.77, 10.53, 10.30,

10.08, 9.86,  9.66,  9.46,  9.27,

9.08,  8.90,  8.73,  8.57,  8.41,

8.25,  8.11,  7.96,  7.82,  7.69,

7.56,  7.43,  7.30,  7.18,  7.07,

6.95,  6.84,  6.73,  6.63,  6.53,

6.41,

};

 

void setup()

{

    Serial.begin(115200);                //115200 시리얼 모니터로 실행

    pinMode(DoSensorPin,INPUT);         //DO센서핀 출력                

    pinMode(DS18S20_Pin,INPUT);          //수온센서핀 출력

    readDoCharacteristicValues(); //                 //EEPROM에서 do특성 값 읽기

   

}

 

void loop()

{

   static unsigned long analogSampleTimepoint = millis();          

   if(millis()-analogSampleTimepoint > 30U)               //30밀리초마다 아날로그 값 읽기

{

 analogSampleTimepoint = millis();   

analogBuffer[analogBufferIndex] = analogRead(DoSensorPin);   //아날로그 값을 읽어 버퍼에 저장

analogBufferIndex++;

     if(analogBufferIndex == SCOUNT)

         analogBufferIndex = 0;

   }

  

   static unsigned long tempSampleTimepoint = millis();

   if(millis()-tempSampleTimepoint > 500U)                //500밀리초마다 온도 값 읽기

   {

      tempSampleTimepoint = millis();                 

      float temperature();                          //수온센서코딩

       byte data[12];                

 byte addr[8];

 if ( !ds.search(addr)) {

   ds.reset_search();

   return -1000;

 }

 if ( OneWire::crc8( addr, 7) != addr[7]) {          //CRC 오류검사(네트워크를 통하여 데이터를 전송할때 전송된 데이터에 오류가 있는지를 확인하기 위한 체크값을 결정하는 방식)

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

 byte present = ds.reset();

 ds.select(addr); 

 ds.write(0xBE);

 

 

for (int i = 0; i < 9; i++) {            //i가 증가할때마다 ds(수온센서 핀)의 데이터를 읽어낸다

  data[i] = ds.read();                                                         

 }

 

 ds.reset_search();

 byte MSB = data[1];             //최상위 비트는 data[1]

 byte LSB = data[0];              //최하위 비트는 data[0]

 float tempRead = ((MSB << 8) | LSB);

 float TemperatureSum = tempRead / 16;

 return TemperatureSum;                                                                   

}

 

        

 

   static unsigned long printTimepoint = millis();

   if(millis()-printTimepoint > 1000U)            // 출력되는데 1000밀리초 걸린다

   {

      printTimepoint = millis();         // 출력되는 시간 1000밀리초

      for(copyIndex=0;copyIndex<SCOUNT;copyIndex++)    // 카운트합계만큼 0이상부터 반복

      {

        analogBufferTemp[copyIndex]= analogBuffer[copyIndex];

      }

      averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0;

      Serial.print(F("Temperature:"));

      Serial.print(temperature,1);

      Serial.print(F("^C"));        // 평균 전압 구하는식           //온도 출력

      doValue = pgm_read_float_near( &SaturationValueTab[0] + (int)(SaturationDoTemperature+0.5) ) * averageVoltage / SaturationDoVoltage;  //calculate the do value, doValue = Voltage / SaturationDoVoltage * SaturationDoValue(with temperature compensation)

      Serial.print(F(",  DO Value:"));

      Serial.print(doValue,2);

      Serial.println(F("mg/L"));       // do값 구하는 식           //do값 출력

   }

  

   if(serialDataAvailable() > 0)   // 유효한 데이터 값이 0이상일 때

   {

      byte modeIndex = uartParse();   // 받은 명령을 분석한다

      doCalibration(modeIndex);    // do보정함수 호출한다

   }

}

 

 

 

 

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)  // CALIBRATION입력시 보정모드 들어가기

        modeIndex = 1;        // 순서 1번

    else if(strstr(receivedBuffer, "EXIT") != NULL)   // EXIT입력시 보정모드 종료

        modeIndex = 3;     // 순서 3번

    else if(strstr(receivedBuffer, "SATCAL") != NULL)    // SATCAL입력시 보정성공여부 확인

        modeIndex = 2;      // 순서 2번

    return modeIndex;

}

 

void doCalibration(byte mode)      // do보정 모드

{

    char *receivedBufferPtr;

    static boolean doCalibrationFinishFlag = 0,enterCalibrationFlag = 0;

    float voltageValueStore;

    switch(mode)

    {

      case 0:

      if(enterCalibrationFlag)

         Serial.println(F("Command Error"));    // 입력 시 최종 보정 완료

      break;

     

      case 1:

      enterCalibrationFlag = 1;  

      doCalibrationFinishFlag = 0;

      Serial.println();

      Serial.println(F(">>>Enter Calibration Mode<<<"));         

      Serial.println(F(">>>Please put the probe into the saturation oxygen water! <<<"));

      Serial.println();

      break;

    

     case 2:

      if(enterCalibrationFlag)

      {

         Serial.println();

         Serial.println(F(">>>Saturation Calibration Finish!<<<"));

         Serial.println();

         EEPROM_write(SaturationDoVoltageAddress, averageVoltage);

         EEPROM_write(SaturationDoTemperatureAddress, temperature);

         SaturationDoVoltage = averageVoltage;

         SaturationDoTemperature = temperature;

         doCalibrationFinishFlag = 1;

      }

      break;

 

        case 3:

        if(enterCalibrationFlag)

        {

            Serial.println();

            if(doCalibrationFinishFlag)     

               Serial.print(F(">>>Calibration Successful"));

            else

              Serial.print(F(">>>Calibration Failed"));      

            Serial.println(F(",Exit Calibration Mode<<<"));

            Serial.println();

            doCalibrationFinishFlag = 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 readDoCharacteristicValues(void)              //EEPROM에 저장된 do값을 읽음

{

    EEPROM_read(SaturationDoVoltageAddress, SaturationDoVoltage);  //EEPROM에 저장된 포화산소전압주소, 포화do전압 읽어냄

    EEPROM_read(SaturationDoTemperatureAddress, SaturationDoTemperature);  //EEPROM에 저장된 포화do온도 주소, 포화do온도 읽어냄

 

    if(EEPROM.read(SaturationDoVoltageAddress)==0xFF && EEPROM.read(SaturationDoVoltageAddress+1)==0xFF && EEPROM.read(SaturationDoVoltageAddress+2)==0xFF && EEPROM.read(SaturationDoVoltageAddress+3)==0xFF)

    {

      SaturationDoVoltage = 1127.6;   //default voltage:1127.6mv

      EEPROM_write(SaturationDoVoltageAddress, SaturationDoVoltage);

    }

    if(EEPROM.read(SaturationDoTemperatureAddress)==0xFF && EEPROM.read(SaturationDoTemperatureAddress+1)==0xFF && EEPROM.read(SaturationDoTemperatureAddress+2)==0xFF && EEPROM.read(SaturationDoTemperatureAddress+3)==0xFF)

    {

      SaturationDoTemperature = 25.0;   //default temperature is 25^C

      EEPROM_write(SaturationDoTemperatureAddress, SaturationDoTemperature);

    }   

}

이전글   |    소모임에 관해서 2018-09-16
다음글   |    어댑터 사용 질문있습니다. 2018-09-21