Визуализация данных

Mar 20, 2018 14:04


Продолжение статьи

В  процессе эксплуатации обнаружены ошибки и проведены некоторые  доработки. Данные передаются в реальном времени и отображаются на экране  компьютера, а также сохраняются в таблице. Недоработок и пожеланий еще  полно, надо сделать панорамирование графика мышью, автоподстройку данных  -перерисовку при превышении параметров, изменение интервала опроса и  т.д., но сейчас все проекты заморожены по причине переезда.

Коротко  о результатах - датчик из предыдущих постов провел в земле больше чем  полгода, проект пришлось свернуть. Выглядит он нормально, дефекты есть,  но вполне рабочий. Позже на месяц воткнул в землю  штырь от палатки, он  похоже хромированный, на нем образовалась коррозия.

Росла у меня  малина и листья у нее с коричневой бахромой, возможно что то с почвой(но  она у меня однородная, но в разных мешках, где что то могло попасть),  хотя китайский PHметр показывает норму. Правда он всегда показывает одно  и тоже, больше нечего было проверить, кроме воды.

Фотки пока разместить не могу.

Код Arduino



#include "Timer.h"
#include
#include
#include
#include
#define AM2315_I2C_ADDRESS 0x69
#define NUM_READS 2    // Number of sensor reads for filtering

DS3231 clock;
RTCDateTime dt;
Adafruit_AM2315 am2315;
LiquidCrystal_I2C lcd(0x27,20,4);  //

long buffer[NUM_READS];
long sensor1;
int ind;
int inByte = 0;         // incoming serial byte

typedef struct {        // Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs)
 int moisture;
 long resistance;
} values;

const long knownResistor = 1500;  // Constant value of known resistor in Ohms
int supplyVoltage;                // Measured supply voltage
int sensorVoltage;                // Measured sensor voltage

values valueOf[NUM_READS];        // Calculated moisture percentages and resistances to be sorted and filtered
int i;                            // Simple index variable
unsigned long previousMillis = 0;        /
const long interval = 100;  
Timer t;

void setup()
{
Serial.begin(9600);
 lcd.init();                      
 lcd.backlight();
 clock.begin();
 int tickEvent = t.every(30000, graf); // период опроса датчиков - 30 сек
 int tickInd = t.every(1000, Ind); // период опроса датчика AM2315 - 1 сек, иначе ошибка
 // Pin 6,7 is for sensor 1
 pinMode(6, OUTPUT);    
 pinMode(7, OUTPUT);
 establishContact();  // send a byte to establish contact until receiver responds
}
 void loop()
{  
 t.update();
};

void Ind()
{  
 dt = clock.getDateTime();
 lcd.setCursor(0, 0); //  
 lcd.print(dt.month);  lcd.print("/");
 lcd.print(dt.day);    lcd.print(" ");
 lcd.print(dt.hour);   lcd.print(":");
 lcd.print(dt.minute); lcd.print(":");
 lcd.print(dt.second);lcd.print(" T:"); lcd.print(clock.readTemperature());
 lcd.setCursor(0, 3); // 1 строка
 lcd.print("Hum: "); lcd.print(am2315.readHumidity());
 lcd.print(" T: "); lcd.print(am2315.readTemperature());
 };
void graf()
{
 measure(1,6,7,1);
 long read1 = average();
 measure(1,7,6,0);
 long read2= average();
 sensor1 = (read2 + read1)/2;
 lcd.setCursor(0,1);
 lcd.print ("R1=" ); lcd.print (read1); lcd.print ("R2=" );lcd.print (read2);
 lcd.setCursor(0,2);
 lcd.print ("sensor = ");lcd.print (sensor1);

float Hum = (am2315.readHumidity());
 float Tem =(am2315.readTemperature());
 if (Serial.available() > 0) {
     writeInt(576);//sensor1
     writeFloat (Tem);
     writeFloat(Hum);
  }
}

void measure (int sensor, int phase_b, int phase_a, int analog_input)
{
 for (i=0; i    // Read 1 pair of voltage values
   digitalWrite(phase_a, HIGH);                 // set the voltage supply on
   delayMicroseconds(25);
   supplyVoltage = analogRead(analog_input);   // read the supply voltage
   delayMicroseconds(25);
   digitalWrite(phase_a, LOW);                  // set the voltage supply off
   delay(1);
   digitalWrite(phase_b, HIGH);                 // set the voltage supply on
   delayMicroseconds(25);
   sensorVoltage = analogRead(analog_input);   // read the sensor voltage
   delayMicroseconds(25);
   digitalWrite(phase_b, LOW);                  // set the voltage supply off
   // Calculate resistance
   // the 0.5 add-term is used to round to the nearest integer
   // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction
   long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage) ;
   delay(1);
   addReading(resistance);
 }
}

// Averaging algorithm
void addReading(long resistance){
 buffer[ind] = resistance;
 ind++;
 if (ind >= NUM_READS) ind = 0;
}

long average(){
 long sum = 0;
 for (int i = 0; i < NUM_READS; i++){
   sum += buffer[i];
 }
 return (long)(sum / NUM_READS);
}

void establishContact() {
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis >= interval) {
   previousMillis = currentMillis;
   Serial.print('A');   // символ начала передачи данных
 }
}

void writeInt(int reg) //преобразование int to byte
{
 byte  ch=byte(reg>>8);
 byte  cl=byte(reg & 0xFF);
 Serial.write(cl);
 Serial.write(ch);
}

void writeFloat (float val) //преобразование float to byte
{
  union u_tag {
  byte x[4];
  float fval;
} u;
 byte *x = (byte *)&val;
 for (int i=0; i<4; i++) {
   Serial.write(x[i]);
  }
}

Программа Processing

import processing.serial.*;
import grafica.*;
import java.util.Date;

Serial myPort; //
int[] serialInArray = new int[10]; // байт приема
int serialCount = 0;  
boolean firstContact = false;
int l, li =0;
int min, max,min1, max1, min2, max2;
float minH, maxH,minT, maxT;
int MinY, MaxY;

GPlot plot, plot1, plot2 , plot_Right;
String received; // данные, получаемые с последовательного порта

int points = 2900; // число точек в графике
int totalPoints = 3000; // число точек в графике
// параметры фильтра Калмана
float P = 1.0; //gladkost 0.2
float varP = pow(0.1, 1);
float varM = pow(0.5, 1);
float K = 1.0;
float Kalman = 20.0;
float KalmanPlot=0.0;

float Hum, Tem, Sval, Humut, Temper ;
int val;

Table table;
int readingCounter = 0;
String file, filename ;

void setup() {
frameRate(2);
size (1200,900);  
MinY=400;
MaxY=900;

println(Serial.list());
String portName = "COM10";
//Serial.list()[2];
myPort = new Serial(this, portName, 9600);

GPointsArray pTem = new GPointsArray(points);  
GPointsArray pVlag = new GPointsArray(points);  
GPointsArray pR = new GPointsArray(points);

plot = new GPlot(this);  
plot.setPos(25, 25); // set the position of to left corner of plot  
plot.setDim(1000, 700); // set plot size

plot.setXLim(0, totalPoints); // set x limits  
plot.setYLim(MinY, MaxY); // set y limits  
plot.setPointColor(color(0, 0, 255));  
plot.setTitleText("Датчик влажности почвы");  
plot.getXAxis().setAxisLabelText("время");  
plot.getYAxis().setAxisLabelText("влажность");
plot.getXAxis().setNTicks(15);
plot.setPoints(pTem);
plot.setPointSize(4.0);
plot.addLayer("Kalman", pTem);

plot1 = new GPlot(this);
plot1.setPos(plot.getPos());
plot1.setDim(plot.getDim());
plot1.setXLim(0, totalPoints); // set x limits
plot1.setYLim(MinY, MaxY); // set y limits
plot1.setPointColor(color(255, 0, 0));
plot1.setPoints(pVlag);  
plot1.setPointSize(2.0);

plot2 = new GPlot(this);
plot2.setPos(plot.getPos());
plot2.setMar(plot.getMar());
plot2.setDim(plot.getDim());
plot2.setXLim(0, totalPoints); // set x limits
plot2.setYLim(MinY, MaxY); // set y limits   
plot2.setPointColor(color(0 , 255, 0));
plot2.setPoints(pR);  
plot2.setPointSize(4.0);

plot_Right = new GPlot(this);
plot_Right.setPos(plot.getPos());
plot_Right.setMar(plot.getMar());
plot_Right.setDim(plot.getDim());
plot_Right.setAxesOffset(4);
plot_Right.getYAxis().setNTicks(10);
plot_Right.getRightAxis().setAxisLabelText("Температура");
plot_Right.getRightAxis().setDrawTickLabels(true);
//plot.activatePanning();

int s = second();
int m = minute();
int h = hour();
int d = day();
int mo = month();
int y = year();

String filename = str(d)+ "_" + str(mo) + "_" + str(y) + ("_") + str(h) + ("_") + str(m);
table = new Table();

table.addColumn("Date");
table.addColumn("R");// SENSOR
table.addColumn("T1");// TEMPER AC
table.addColumn("V1");// VLAG AC
file = ("data/" +filename + ".csv");  //имя таблицы
}

void draw() {  
background(255);
if (li==1) {noLoop(); } //запрет обновления
if (li==0) {redraw();  // очередное обновление

//распаковка данных
val = serialInArray[1]*256 + serialInArray[0];  
          int asInt = (serialInArray[2] & 0xFF)
           | ((serialInArray[3] & 0xFF) << 8)
           | ((serialInArray[4] & 0xFF) << 16)
           | ((serialInArray[5] & 0xFF) << 24);
Tem = Float.intBitsToFloat(asInt);
       asInt = (serialInArray[6] & 0xFF)
           | ((serialInArray[7] & 0xFF) << 8)
           | ((serialInArray[8] & 0xFF) << 16)
           | ((serialInArray[9] & 0xFF) << 24);
Hum = Float.intBitsToFloat(asInt);
//локальные /максимумы, минимумы
if (val>max) max=val;
if (l == 3) { min=max; }  
if (valif (Hum>maxH) maxH=Hum;  
if (l == 2)  minH=maxH;   
if (Hum
P = P + varP;  //сглаживание
K = P / (P + varM);  
Kalman = K * val + (1 - K) * Kalman;  
P = (1 - K) * P;

KalmanPlot = map(Kalman, 18, 30, 0, height); //масштабирование графика - пока руками  
float MinYF = MinY;
float MaxYF = MaxY;
Temper= map (Tem, 0, 40, MinYF, MaxYF);
Humut= map (Hum, 0, 80, MinYF, MaxYF);

plot.beginDraw();  
plot.drawBackground();  
plot.drawBox();  
plot.drawXAxis();  
plot.drawYAxis();  
plot.drawTopAxis();  
plot.drawRightAxis();  
plot.drawTitle();

//график левая ось
plot.drawPoints();
plot.getLayer("Kalman").drawPoints();  
plot.drawLegend(new String[] {("Температура ="+ Tem), ("Влажность = "+ Hum)}, new float[] {0.12, 0.4}, new float[] {0.92, 0.92});  
plot.drawLegend(new String[] {("Max ="+ max), ("Min = "+ min)}, new float[] {0.12, 0.4}, new float[] {0.87, 0.87});
plot.drawGridLines(GPlot.BOTH);//линии клетки
//plot.activatePanning();
//plot.activateZooming(1.1, CENTER, CENTER);// центрирование данных

plot.endDraw();   
plot1.beginDraw();
plot1.drawPoints();
plot1.endDraw();

//правая ось
plot2.beginDraw();
plot2.drawPoints();
plot2.endDraw();

//plot_Right.setYLim(calc(plot.getYLim()));
 plot_Right.setYLim(3.0,40.0);
 plot_Right.beginDraw();
 plot_Right.drawRightAxis();
 plot_Right.endDraw();

l++;  
plot.addPoint(l,Temper);  
plot1.addPoint(l, val);  
plot.addPoint(l, Kalman,"Kalman");  
plot2.addPoint(l, Humut);

int s = second();
int m = minute();
int h = hour();
int d = day();
int mo = month();
int y = year();

//запись в таблицу
TableRow newRow = table.addRow();
newRow.setInt("R",val);
String DateTab = str(d)+ "." + str(mo) + "." +  str(y) + (" ") +  str(h) + (":") + str(m) + (":") + str(s);
newRow.setString("Date",DateTab);
newRow.setFloat ("T1", Tem);
newRow.setFloat ("V1", Hum);

readingCounter++;
saveTable(table, file );  
noLoop();
}
}
//взаимодействие с COM портом
void serialEvent(Serial myPort) {
int inByte = myPort.read();
if (firstContact == false) {
 if (inByte == 'A') {  
   myPort.clear(); // clear the serial port buffer
   firstContact = true; // you've had first contact from the microcontroller
   myPort.write('A'); // ask for more  
 }  
   myPort.clear(); // clear the serial port buffer
   myPort.write('B');
   myPort.write("600");// изменить
}  
else {
 serialInArray[serialCount] = inByte;
 //println(serialInArray[serialCount]+ " " + serialCount);
 serialCount++;

if (serialCount > 9 ) {
   li=0;
   loop();

myPort.write('A');
   serialCount = 0;
   }
 }
}

arduino; processing

Previous post
Up