2016-02-23 76 views
1

我從模擬輸入(A0引腳)和模擬輸入(A1引腳)的電流信號(電壓形式)中取出電壓信號,將其轉換爲數字形式,然後對其進行處理以獲得Vrms ,Irms和相位數據。然後,我將它存儲在「dataString」中,並將其寫入SD卡。arduino中浮點變量的精度

我面臨的問題是,在功率因數的浮點計算的某個地方,我做了一些錯誤,因爲答案被「顯示爲」1.00,而在4.97(度)的角度,我應該得到COS(4.97)= 0.9962(圖片附) Image1

雖然該方案使用的是正確的值,即,在進一步的計算0.9962(即實際功率),但我想正確地高達4個點後,以顯示功率因數小數。這裏是我的程序代碼

#include <SPI.h> 
#include <SD.h> 

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

RTC_DS1307 RTC; 
#include "DHT.h" 

#define DHTPIN 8 
#define DHTTYPE DHT21 
DHT dht(DHTPIN, DHTTYPE); 

#define count 100 

const int analogInPin1 = A1; 
const int analogInPin0 = A0; 

const int chipSelect = 10; 

void setup() 
{ 
    Serial.begin(115200); 
     Wire.begin(); 
     RTC.begin(); 

     if (! RTC.isrunning()) { 
     Serial.println("#RTC is NOT running!"); 
     // following line sets the RTC to the date & time this sketch was compiled 
     // uncomment it & upload to set the time, date and start run the RTC! 
     // RTC.adjust(DateTime(__DATE__, __TIME__)); 
     } 
    analogReference(DEFAULT); 
    Serial.println("#DHTxx test!"); 

    dht.begin(); 


    Serial.print("#Initializing SD card..."); 

    // see if the card is present and can be initialized: 
    if (!SD.begin(chipSelect)) { 
    Serial.println("#Card failed, or not present"); 
    // don't do anything more: 
    return; 
    } 
    Serial.println("#card initialized."); 
    Serial.println("#Date  Time   Vrms   Irms   Phase  Power_factor  Apparent_Power  Real_Power  Humidity   Temperature"); 


} 

void loop() 
{ 


    float sensorValue0[count];   
    float sumSensorValue0=0; 
    float meanSensorValue0=0; 
    float Vrms=0; 
    sumSensorValue0=0; 

    float sensorValue1[count];   
    float sumSensorValue1=0; 
    float meanSensorValue1=0; 
    float Irms=0; 
    int i=0; 
    sumSensorValue1=0; 

    DateTime now = RTC.now(); 

    for(i=0;i<count;i++) 
    { 
    sensorValue1[i] = (analogRead(analogInPin1)*4.8)-3200; //4.8 mV (i.e. 0.0048 Volts) per unit.. Vref/1024.. here Vref = 5 V ....//3.220 V = Offset 
    sensorValue0[i] = (analogRead(analogInPin0)*4.8)-3200; 

    sensorValue1[i] = sensorValue1[i]*sensorValue1[i]; 
    sensorValue0[i] = sensorValue0[i]*sensorValue0[i]; 
    sumSensorValue1+= sensorValue1[i]; 
    sumSensorValue0+= sensorValue0[i]; 
    } 

    meanSensorValue1 = sumSensorValue1/count; 
    meanSensorValue0 = sumSensorValue0/count; 
    Irms = (sqrt(meanSensorValue1)*0.06); //60/1000 = 0.06 Calibrating 60 Ampere/1 Volt to give us the value for X amperes 
    Vrms = (sqrt(meanSensorValue0)*0.3565); // Multiplying with 356.5(the product of ratios of 9V and 12 V transformer) gives the measured voltage in mV.. dividing by 1000 to bring it to Volts from mV 
    float appPower; 
    appPower = Vrms*Irms; 

float Vsense=0; 
float LastVsense=0; 
float Isense=0; 
float LastIsense=0; 
float phase; 
float mean_phase=0; 
float counter=0; 
unsigned long timer; 

for(int i=0;i<200;i++) 
    { 
    // put your main code here, to run repeatedly: 
Isense=analogRead(A1)*4.8-3200; 
Vsense=analogRead(A0)*4.8-3220; 
if(Vsense>= 0 && LastVsense<0 && Isense<0) 
    { 
    timer = micros(); 
    do{ 
    Isense=analogRead(A1)*4.8-3200; 
    }while(!(Isense>=0)); 
    timer = micros()-timer; 
    phase = (timer*360.0)/20000.0; 
    mean_phase+=phase; 
    counter+=1.0; 
    }else; 

    if(Isense >= 0 && LastIsense < 0 && Vsense < 0) 
    { 
    timer = micros(); 
    do{ 
    Vsense=analogRead(A0)*4.8-3200; 
    }while(!(Vsense>=0)); 
    timer = micros()-timer; 
    phase = (timer*360.0)/20000.0; 
    mean_phase+=phase; 
    counter+=1.0; 
    }else; 

LastIsense = Isense; 
LastVsense = Vsense; 

} 
    mean_phase= mean_phase/counter; 


    float realPower; 
    float powerFactor; 
    float phase_rad= mean_phase*PI/180.0; 
    powerFactor =cos(phase_rad); //phase converted to radian for cosine function 
    realPower = Vrms*Irms*powerFactor; 

    String dataString = ""; 

    float h = dht.readHumidity(); 
    float t = dht.readTemperature(); 

    if (isnan(t) || isnan(h)) { 
    Serial.println("#Failed to read from DHT"); 
    } else { 
    dataString+=now.year(), DEC; 
    dataString+="/"; 
    dataString+=now.month(), DEC; 
    dataString+="/"; 
    dataString+=now.day(), DEC; 
    dataString+=" "; 
    dataString+=now.hour(), DEC; 
    dataString+=":"; 
    dataString+=now.minute(), DEC; 
    dataString+=":"; 
    dataString+=now.second(), DEC; 
    dataString+="   "; 
    dataString+=Vrms; 
    dataString+="   "; 
    dataString+=Irms; 
    dataString+="   "; 
    dataString+=mean_phase; 
    dataString+="   "; 
    dataString+=powerFactor; 
    dataString+="     "; 
    dataString+=appPower; 
    dataString+="     "; 
    dataString+=realPower; 
    dataString+="   "; 
    dataString+=h; 
    dataString+="   "; 
    dataString+=t; 

    } 
    // open the file. note that only one file can be open at a time, 
    // so you have to close this one before opening another. 
    File dataFile = SD.open("datalog.dat", FILE_WRITE); 

    // if the file is available, write to it: 
    if (dataFile) { 
    dataFile.println(dataString); 
    dataFile.close(); 
    // print to the serial port too: 
    Serial.println(dataString); 
    } 
    // if the file isn't open, pop up an error: 
    else { 
    Serial.println("#error opening datalog.dat"); 
    } 

    delay(10000); 
} 

回答

1

雖然該方案使用的是正確的值,即0.9962在進一步的計算...

指向問題在您的打印的代碼之中。

更具體地說,我懷疑這條線可能會引起麻煩:

dataString+=powerFactor; 

您使用String類,所以WString.cpp是相關的文件。

如果我們檢查它,我們發現,上線409(至少在我的版本的Arduino,1.6.7 IIRC)的,則+經營者申報的花車,它只是簡單地調用concat(float),其上可以找到線323:

unsigned char String::concat(float num) 
{ 
    char buf[20]; 
    char* string = dtostrf(num, 4, 2, buf); 
    return concat(string, strlen(string)); 
} 

如果讀取dtostrf文檔,你會發現,這是轉換的雙重(浮子被提升)將字符串與4點2位精度的寬度。

解決此問題的最簡單方法是使用dtostrf將float轉換爲具有所需精度的字符串,然後將該字符串附加到String實例。