arduino中浮动变量的精度
我从模拟输入端(A0引脚)获取电压信号,从模拟输入端(A1引脚)获取电流信号(以电压的形式),将其转换为数字信号,然后对其进行处理,以获得Vrms、Irms和相位数据。然后我将其存储在“数据串”中,并将其写入SD卡 我面临的问题是,在功率因数的浮点计算中,我做了一些错误的事情,因此答案“显示为”1.00,而在4.97(度)的角度下,我应该得到cos(4.97)=0.9962(附图) 虽然程序在进一步计算中使用了正确的值,即0.9962(实际功率),但我希望它能在小数点后4点正确显示功率因数。这是我的程序代码arduino中浮动变量的精度,arduino,Arduino,我从模拟输入端(A0引脚)获取电压信号,从模拟输入端(A1引脚)获取电流信号(以电压的形式),将其转换为数字信号,然后对其进行处理,以获得Vrms、Irms和相位数据。然后我将其存储在“数据串”中,并将其写入SD卡 我面临的问题是,在功率因数的浮点计算中,我做了一些错误的事情,因此答案“显示为”1.00,而在4.97(度)的角度下,我应该得到cos(4.97)=0.9962(附图) 虽然程序在进一步计算中使用了正确的值,即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);
}
#包括
#包括
#包括
#包括“RTClib.h”
RTC_DS1307 RTC;
#包括“DHT.h”
#定义DHTPIN 8
#定义DHT类型DHT21
DHT-DHT(DHTPIN,DHTTYPE);
#定义计数100
const int类比inpin1=A1;
常数int analogInPin0=A0;
常数int chipSelect=10;
无效设置()
{
序列号开始(115200);
Wire.begin();
RTC.begin();
如果(!RTC.isrunning()){
Serial.println(“RTC未运行!”);
//以下行将RTC设置为编译此草图的日期和时间
//取消注释并上载以设置时间、日期和开始运行RTC!
//RTC.调整(日期时间(_日期,_时间));
}
模拟参考(默认);
Serial.println(“#dhtx测试!”);
dht.begin();
串行打印(#初始化SD卡…);
//查看该卡是否存在并可以初始化:
如果(!SD.begin(芯片选择)){
Serial.println(“#卡失败或不存在”);
//不要再做任何事情:
返回;
}
Serial.println(“#卡已初始化”);
Serial.println(“日期时间Vrms Irms相位功率因数视在功率实际功率湿度温度”);
}
void循环()
{
浮点传感器值0[计数];
浮点数传感器值0=0;
浮点平均传感器值0=0;
浮动Vrms=0;
sumSensorValue0=0;
浮点传感器值1[计数];
浮点数传感器值1=0;
浮点平均值传感器值1=0;
浮动Irms=0;
int i=0;
sumSensorValue1=0;
DateTime now=RTC.now();
对于(i=0;i=0));
定时器=微秒()-定时器;
相位=(定时器*360.0)/20000.0;
平均相位+=相位;
计数器+=1.0;
}否则;
LastIsense=Isense;
LastVsense=Vsense;
}
平均相位=平均相位/计数器;
浮动实权;
浮动功率因数;
浮动相位=平均相位*PI/180.0;
功率因数=cos(相位\弧度)//余弦函数的相位转换为弧度
realPower=Vrms*Irms*功率因数;
字符串dataString=“”;
浮动h=dht.read湿度();
浮点数t=dht.readTemperature();
if(isnan(t)| | isnan(h)){
Serial.println(“#从DHT读取失败”);
}否则{
dataString+=now.year(),12月;
数据字符串+=“/”;
dataString+=now.month(),12月;
数据字符串+=“/”;
dataString+=now.day(),12月;
数据字符串+=“”;
dataString+=now.hour(),DEC;
数据字符串+=“:”;
dataString+=now.minute(),DEC;
数据字符串+=“:”;
dataString+=now.second(),DEC;
数据字符串+=“”;
数据串+=Vrms;
数据字符串+=“”;
dataString+=Irms;
数据字符串+=“”;
数据串+=平均相位;
数据字符串+=“”;
数据串+=功率因数;
数据字符串+=“”;
dataString+=appPower;
数据字符串+=“”;
dataString+=realPower;
数据字符串+=“”;
数据串+=h;
数据字符串+=“”;
数据串+=t;
}
//打开文件。请注意,一次只能打开一个文件,
//所以在打开另一个之前,你必须先关闭这个。
文件dataFile=SD.open(“datalog.dat”,文件写入);
//如果文件可用,请写入:
如果(数据文件){
dataFile.println(数据字符串);
dataFile.close();
//也可以打印到串行端口:
Serial.println(数据字符串);
}
//如果文件未打开,则弹出一个错误:
否则{
Serial.println(“#打开datalog.dat时出错”);
}
延迟(10 000);
}
尽管程序在进一步计算中使用了正确的值,即0.9962
这就指向了打印代码中的问题
更具体地说,我怀疑这条线路可能会引起麻烦:
dataString+=powerFactor;
您使用的是String类,因此WString.cpp
是相关文件
如果我们检查它,我们会发现在第409行(至少在我的Arduino版本1.6.7 IIRC中,+
操作符是为float声明的,它只调用concat(float)
,可以在第323行找到:
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
如果您阅读dtostf
文档,您会发现这是在将double(浮点值被提升)转换为宽度为4、精度为2位的字符串
解决这个问题的最简单方法是使用dtostf
将浮点值转换为具有所需精度的字符串,然后将该字符串附加到字符串实例中