2016-02-23 39 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实例。