mirror of
https://github.com/eddyem/tsys01.git
synced 2026-02-02 21:35:05 +03:00
fixed tmean=NaN, constrict valid T range to med(T)+=3RMS
This commit is contained in:
parent
9bfb542dfc
commit
3202beec31
@ -1,6 +1,7 @@
|
|||||||
## Serial interface commands (ends with '\n'), small letter for only local processing:
|
## Serial interface commands (ends with '\n'), small letter for only local processing:
|
||||||
- **0...7** send message to Nth controller, not broadcast (after number should be CAN command)
|
- **0...7** send message to Nth controller, not broadcast (after number should be CAN command)
|
||||||
- **@** set/reset debug mode
|
- **@** set/reset debug mode
|
||||||
|
- **A** allow given node to speak
|
||||||
- **a** get raw ADC values
|
- **a** get raw ADC values
|
||||||
- **B** send dummy CAN messages to broadcast address
|
- **B** send dummy CAN messages to broadcast address
|
||||||
- **b** get/set CAN bus baudrate
|
- **b** get/set CAN bus baudrate
|
||||||
@ -9,20 +10,21 @@
|
|||||||
- **d** get current CAN address of device
|
- **d** get current CAN address of device
|
||||||
- **Ee** end temperature scan
|
- **Ee** end temperature scan
|
||||||
- **Ff** turn sensors off
|
- **Ff** turn sensors off
|
||||||
- **g** group (sniffer) CAN mode (print to USB terminal all incoming CAN messages with alien IDs)
|
- **g** sniffer CAN mode (print to USB terminal all incoming CAN messages with alien IDs)
|
||||||
- **Hh** switch I2C to high speed (100kHz)
|
- **Hh** switch I2C to high speed (100kHz)
|
||||||
- **Ii** (re)init sensors
|
- **Ii** (re)init sensors
|
||||||
- **Jj** get MCU temperature
|
- **Jj** get MCU temperature
|
||||||
- **Kk** get values of U and I
|
- **Kk** get values of U and I
|
||||||
- **Ll** switch I2C to low speed (default, 10kHz)
|
- **Ll** switch I2C to low speed (default, 10kHz)
|
||||||
- **Mm** change master id to 0 (**m**) / broadcast (**M**)
|
|
||||||
- **N** get build number
|
- **N** get build number
|
||||||
- **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands are local!)
|
- **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands are local!)
|
||||||
- **P** ping everyone over CAN
|
- **P** ping everyone over CAN
|
||||||
- **Qq** get system time
|
- **Qq** get system time
|
||||||
- **Rr** reinit I2C
|
- **Rr** reinit I2C
|
||||||
|
- **S** shut up given node
|
||||||
- **s** send CAN message (format: ID data[0..8], dec, 0x - hex, 0b - binary)
|
- **s** send CAN message (format: ID data[0..8], dec, 0x - hex, 0b - binary)
|
||||||
- **Tt** start single temperature measurement
|
- **Tt** start single temperature measurement
|
||||||
|
- **U** USB status of given node (0 - off)
|
||||||
- **u** unique ID (default) CAN mode
|
- **u** unique ID (default) CAN mode
|
||||||
- **Vv** very low speed
|
- **Vv** very low speed
|
||||||
- **Xx** go into temperature scan mode
|
- **Xx** go into temperature scan mode
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
BTA mirror temperature network daemon
|
BTA mirror temperature network daemon
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Gather information from temperature sensors and send it over ethernet by network request like
|
Gather information from temperature sensors and send it over ethernet by network request.
|
||||||
|
|
||||||
|
## Protocol
|
||||||
|
|
||||||
|
Request format over http:
|
||||||
|
|
||||||
hostname:4444/Tx
|
hostname:4444/Tx
|
||||||
where x is 0 for upper sensors, 1 for lower and 2 for T measured by main controller.
|
where x is 0 for upper sensors, 1 for lower and 2 for T measured by main controller.
|
||||||
hostname:4444/Tmean returns mean temperature
|
hostname:4444/Tmean returns mean temperature
|
||||||
@ -13,15 +18,18 @@ Answer format: "ID X Y T t", where
|
|||||||
- T is measured temperature (degrees Celsium),
|
- T is measured temperature (degrees Celsium),
|
||||||
- t is UNIX-time of last measurement.
|
- t is UNIX-time of last measurement.
|
||||||
|
|
||||||
|
Also you can connect to server by regular INET socket through the same port. Send T0, T1, T2 or Tmean to get data.
|
||||||
|
After data sending server close socket.
|
||||||
|
|
||||||
To look graph over gnuplot utility collect gnuplot javascript files in subdirectory js of web-server
|
To look graph over gnuplot utility collect gnuplot javascript files in subdirectory js of web-server
|
||||||
images storing directory, copy there script 'plot' and run service as
|
images storing directory, copy there script 'plot' and run service as
|
||||||
|
|
||||||
netdaemon -g -s /path/to/web /path/to/log
|
netdaemon -g -s /path/to/web /path/to/log
|
||||||
|
|
||||||
Every 15 minutes it will calculate average values of thermal data and plot three graphs:
|
Every 15 minutes it will calculate average values of thermal data and plot three graphs:
|
||||||
T0.html with top temperatures, T1.html with bottom and Tgrad.html with their differences (T0-T1).
|
T0.html with top temperatures and T1.html with bottom.
|
||||||
|
|
||||||
** Signals
|
## Signals
|
||||||
|
|
||||||
SIGUSR1 - reread temperatures adjustment file
|
SIGUSR1 - reread temperatures adjustment file
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <arpa/inet.h> // inet_ntop
|
#include <arpa/inet.h> // inet_ntop
|
||||||
#include <limits.h> // INT_xxx
|
#include <limits.h> // INT_xxx
|
||||||
|
#include <math.h> // isfinite, sqrt
|
||||||
#include <netdb.h> // addrinfo
|
#include <netdb.h> // addrinfo
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h> // pthread_kill
|
#include <signal.h> // pthread_kill
|
||||||
@ -197,6 +198,7 @@ static void *handle_socket(void *asock){
|
|||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
}else if(strncmp("Tmean", found, 5) == 0){ // send user meanT
|
}else if(strncmp("Tmean", found, 5) == 0){ // send user meanT
|
||||||
|
if(!isfinite(meanT) || meanT < ABS_ZERO_T) break; // wrong value
|
||||||
L = snprintf(tbuf, 128, "%.2f\n", meanT);
|
L = snprintf(tbuf, 128, "%.2f\n", meanT);
|
||||||
if(L != write(sock, tbuf, L)) WARN("write()");
|
if(L != write(sock, tbuf, L)) WARN("write()");
|
||||||
}else if(strncmp("ReBoOt", found, 6) == 0){
|
}else if(strncmp("ReBoOt", found, 6) == 0){
|
||||||
@ -300,6 +302,19 @@ Item quick_select(Item *idata, int n){
|
|||||||
#undef PIX_SORT
|
#undef PIX_SORT
|
||||||
#undef ELEM_SWAP
|
#undef ELEM_SWAP
|
||||||
|
|
||||||
|
// get RMS
|
||||||
|
double sigma(double *data, int n){
|
||||||
|
if(n < 2) return 0.;
|
||||||
|
double sum = 0., sum2 = 0.;
|
||||||
|
for(int i = 0; i < n; ++i){
|
||||||
|
double d = data[i];
|
||||||
|
sum += d;
|
||||||
|
sum2 += d*d;
|
||||||
|
}
|
||||||
|
sum /= n; sum2 /= n;
|
||||||
|
return sqrt(sum2 - sum*sum);
|
||||||
|
}
|
||||||
|
|
||||||
static void process_T(){
|
static void process_T(){
|
||||||
int i, N, p, Num = 0;
|
int i, N, p, Num = 0;
|
||||||
time_t tmeasmax = 0;
|
time_t tmeasmax = 0;
|
||||||
@ -325,22 +340,24 @@ static void process_T(){
|
|||||||
}
|
}
|
||||||
// calculate mean
|
// calculate mean
|
||||||
double Tmed = quick_select(arr, Num);
|
double Tmed = quick_select(arr, Num);
|
||||||
double Tbot = Tmed - 10., Ttop = Tmed + 10.;
|
double rms3 = 3. * sigma(arr, Num);
|
||||||
DBG("Got %d values, Tmed=%g, tmeasmax=%zd", Num, Tmed, tmeasmax);
|
// bounds: +-3RMS
|
||||||
// throw out all more than +-10degrC and calculate meanT
|
double Tbot = Tmed - rms3, Ttop = Tmed + rms3;
|
||||||
|
DBG("Got %d values, Tmed=%g, Trms=%g, tmeasmax=%zd", Num, Tmed, rms3/3., tmeasmax);
|
||||||
|
// throw out all more than +-3RMS and calculate meanT
|
||||||
Num = 0;
|
Num = 0;
|
||||||
double Tsum = 0.;
|
double Tsum = 0.;
|
||||||
// remove bad/old values of N2 controller
|
// remove bad/old values
|
||||||
for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){
|
for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){
|
||||||
if(tmeasmax - tmeasured[p][N][0] > OLDESTTM){ // not longer than 3 minutes ago!
|
if(tmeasmax - tmeasured[p][N][0] > OLDESTTM){ // not longer than 3 minutes ago!
|
||||||
t_last[p][N][0] = -300.;
|
t_last[p][N][0] = WRONG_T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 1; i <= NCTRLR_MAX; ++i){
|
for(i = 1; i <= NCTRLR_MAX; ++i){
|
||||||
for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){
|
for(p = 0; p < 2; ++p) for(N = 0; N <= NCHANNEL_MAX; ++N){
|
||||||
double T = t_last[p][N][i];
|
double T = t_last[p][N][i];
|
||||||
if(T > Ttop || T < Tbot || tmeasmax - tmeasured[p][N][i] > OLDESTTM){ // not longer than 3 minutes ago!
|
if(T > Ttop || T < Tbot || tmeasmax - tmeasured[p][N][i] > OLDESTTM){ // not longer than 3 minutes ago!
|
||||||
t_last[p][N][i] = -300.;
|
t_last[p][N][i] = WRONG_T;
|
||||||
}else{
|
}else{
|
||||||
DBG("t_last[%d][%d][%d]=%.1f, measuredt=%zd", p, N, i, T, tmeasured[p][N][i]);
|
DBG("t_last[%d][%d][%d]=%.1f, measuredt=%zd", p, N, i, T, tmeasured[p][N][i]);
|
||||||
++Num; Tsum += T;
|
++Num; Tsum += T;
|
||||||
@ -357,16 +374,15 @@ static void process_T(){
|
|||||||
if(Nmean[p][N][i]){
|
if(Nmean[p][N][i]){
|
||||||
Tmean[p][N][i] /= Nmean[p][N][i];
|
Tmean[p][N][i] /= Nmean[p][N][i];
|
||||||
Nmean[p][N][i] = 0;
|
Nmean[p][N][i] = 0;
|
||||||
}else Tmean[p][N][i] = -300.; // no data
|
}else Tmean[p][N][i] = WRONG_T; // no data
|
||||||
}
|
}
|
||||||
plot(Tmean, G->savepath);
|
plot(Tmean, G->savepath);
|
||||||
DBG("memset start");
|
|
||||||
memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1));
|
memset(Tmean, 0, sizeof(double)*2*(NCTRLR_MAX+1)*(NCHANNEL_MAX+1));
|
||||||
DBG("memset end");
|
|
||||||
Nmeanmax = 0;
|
Nmeanmax = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
meanT = Tsum / Num;
|
if(Num) meanT = Tsum / Num;
|
||||||
|
else meanT = WRONG_T; // no good measurements
|
||||||
DBG("got %d, mean: %g\n\n", Num, meanT);
|
DBG("got %d, mean: %g\n\n", Num, meanT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +418,8 @@ static void daemon_(int sock){
|
|||||||
tgot = dtime();
|
tgot = dtime();
|
||||||
process_T(); // get new temperatures & throw out bad results
|
process_T(); // get new temperatures & throw out bad results
|
||||||
for(i = 0; i <= NCTRLR_MAX; ++i){ // scan over controllers
|
for(i = 0; i <= NCTRLR_MAX; ++i){ // scan over controllers
|
||||||
for(int N = 0; N <= NCHANNEL_MAX; ++N) for(int p = 0; p < 2; ++p){
|
int N, p;
|
||||||
|
for(N = 0; N <= NCHANNEL_MAX; ++N) for(p = 0; p < 2; ++p){
|
||||||
double T = t_last[p][N][i];
|
double T = t_last[p][N][i];
|
||||||
char **buf;
|
char **buf;
|
||||||
size_t *len;
|
size_t *len;
|
||||||
|
|||||||
@ -27,6 +27,11 @@
|
|||||||
// timeout for socket closing
|
// timeout for socket closing
|
||||||
#define SOCKET_TIMEOUT (5.0)
|
#define SOCKET_TIMEOUT (5.0)
|
||||||
|
|
||||||
|
// absolute zero: all T < ABS_ZERO_T are wrong
|
||||||
|
#define ABS_ZERO_T (-273.15)
|
||||||
|
// undoubtedly wrong T
|
||||||
|
#define WRONG_T (-300.)
|
||||||
|
|
||||||
void daemonize(char *port);
|
void daemonize(char *port);
|
||||||
const char *gotstr(int N);
|
const char *gotstr(int N);
|
||||||
void TurnOFF();
|
void TurnOFF();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#No dT (Treal = T - dT)
|
#No dT (Treal = T - dT)
|
||||||
|
111 0.1
|
||||||
251 -0.7
|
251 -0.7
|
||||||
320 0.12
|
320 0.12
|
||||||
330 0.15
|
330 0.15
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user