Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
arduino中浮动变量的精度_Arduino - Fatal编程技术网

arduino中浮动变量的精度

arduino中浮动变量的精度,arduino,Arduino,我从模拟输入端(A0引脚)获取电压信号,从模拟输入端(A1引脚)获取电流信号(以电压的形式),将其转换为数字信号,然后对其进行处理,以获得Vrms、Irms和相位数据。然后我将其存储在“数据串”中,并将其写入SD卡 我面临的问题是,在功率因数的浮点计算中,我做了一些错误的事情,因此答案“显示为”1.00,而在4.97(度)的角度下,我应该得到cos(4.97)=0.9962(附图) 虽然程序在进一步计算中使用了正确的值,即0.9962(实际功率),但我希望它能在小数点后4点正确显示功率因数。这

我从模拟输入端(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
将浮点值转换为具有所需精度的字符串,然后将该字符串附加到字符串实例中