This is a continuation of the previous Power Management. This time, I made a meter display side using electron. At this level, it was easy because the thing made with windows worked almost as it was. If you want to see all the code, click here pi_meter
meter_data.json
in json format meter_data.json
on the electron side.index.html
<!DOCTYPE html>
<html>
<header>
<link rel="stylesheet" type="text/css" href="./style.css">
</header>
<head>
<meta charset="UTF-8">
<title>pi_meter</title>
</head>
<body>
<div class="wrapper">
<div class="analog" >
<div class="analog_li" id="a_wtmp">
<img src="./img/a_water_t.png " alt="panel" />
</div>
<div class="analog_li" id="a_otmp">
<img n src="./img/a_oil_t.png " alt="panel" />
</div>
<div class="analog_li" id="a_opls">
<img src="./img/a_oil_p.png " alt="panel" />
</div>
</div>
<div class="degital">
<div class="d_li" id="d_wtmp">
<img class="d_p" src="./img/d_water_t.png " alt="panel" />
</div>
<div class="d_li" id="d_otmp">
<img class="d_p" src="./img/d_oil_t.png " alt="panel" />
</div>
<div class="d_li" id="d_opls">
<img class="d_p" src="./img/d_oil_p.png " alt="panel" />
</div>
</div>
<div class="analog_bar">
<div class="b_bar_li" id="b_wtmp">
<img class="b_a" src="./img/a_bar.png " id="im_wtmp" alt="meter_bar" />
</div>
<div class="b_bar_li" id="b_otmp">
<img class="b_a" src="./img/a_bar.png " alt="meter_bar" />
</div>
<div class="b_bar_li" id="b_opls">
<img class="b_a" src="./img/a_bar.png " id="im_opls" alt="meter_bar" />
</div>
</div>
<div class="digital_str">
<div class="digital_str_li" id="str_wtmp">
</div>
<div class="digital_str_li" id="str_otmp">
</div>
<div class="digital_str_li" id="str_opls">
</div>
</div>
</div>
</body>
<script type="text/javascript" src="script.js"></script>
</html>
main.js
'use strict';
const electron = require("electron");
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;
app.on('window-all-closed', function() {
if (process.platform != 'darwin') {
app.quit();
}
});
app.on('ready', function() {
mainWindow = new BrowserWindow({
frame: true,
fullscreen: true,
});
mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.on('closed', function() {
mainWindow = null;
});
});
script.js
'use strict';
const remote = require('electron').remote;
//Get browser window
const browserWindow = remote.getCurrentWindow();
//Get screen size array[0]Is the width,[1]Is the vertical width
const win_size = browserWindow.getSize();
//Counter used at the opening
var counter=0;
//Maximum number of counters to use at the opening
var animaton_counter=100;//10msec * 200 = 2seconds
//Counter used in the moving opening of each meter
var counter1=0;
var counter2=0;
var counter3=0;
//Value to advance the counter used in the movement opening of each meter
var add_counter1 = 0;
var add_counter2 = (win_size[0]/3)/animaton_counter;
var add_counter3 = (win_size[0]/3*2)/animaton_counter;
//Maximum value of counter = fixed point
var count_max1 = 0;
var count_max2 = (win_size[0]/3);
var count_max3 = (win_size[0]/3*2);
//Get each round meter background
var a_wtmp = document.getElementById("a_wtmp");
var a_otmp = document.getElementById("a_otmp");
var a_opls = document.getElementById("a_opls");
//Get each character meter background
var d_wtmp = document.getElementById("d_wtmp");
var d_otmp = document.getElementById("d_otmp");
var d_opls = document.getElementById("d_opls");
//Acquisition of character display for each character meter
var str_wtmp = document.getElementById("str_wtmp");
var str_otmp = document.getElementById("str_otmp");
var str_opls = document.getElementById("str_opls");
//Acquisition of needle image of each round meter
var bar_wtmp = document.getElementById("b_wtmp");
var bar_otmp = document.getElementById("b_otmp");
var bar_opls = document.getElementById("b_opls");
//Display angle of each meter needle
var rt_wtmp=0;
var rt_otmp=0;
var rt_opls=0;
//Variables for acquiring water temperature and variables for temporary storage
var tmp_wtmp1=0;
var tmp_wtmp2=0;
//Variables for obtaining oil temperature and variables for temporary storage
var tmp_otmp1=0;
var tmp_otmp2=0;
//Variables for acquiring hydraulic pressure and variables for temporary storage
var tmp_opls1=0;
var tmp_opls2=0;
//Wrap flag used in Opening
var turn_flg=0;
//Acquisition of data file for meter
var fs = require('fs');
var filepath = './meter_data.json';
//Window minimization
document.getElementById("im_opls").addEventListener("click", function (e) {
browserWindow.minimize();
});
//End processing
document.getElementById("im_wtmp").addEventListener("click", function (e) {
browserWindow.close();
});
//Movement of round meter
function mv_analog_p(){
a_wtmp.style.left = 0+'px';
a_wtmp.style.top= 0+'px';
a_otmp.style.left = counter2+'px';
a_otmp.style.top= 0+'px';
a_opls.style.left = counter3+'px';
a_opls.style.top= 0+'px';
}
//Moving the character meter
function mv_dgital_p(){
d_wtmp.style.left = 0+'px';
d_wtmp.style.top= (win_size[0]/3)+'px';
d_otmp.style.left = counter2+'px';
d_otmp.style.top= (win_size[0]/3)+'px';
d_opls.style.left = counter3+'px';
d_opls.style.top= (win_size[0]/3)+'px';
}
//Moving the display for the modifier
function mv_dgital_str(){
str_wtmp.style.right = (counter3+(win_size[0]/12))+'px';
str_wtmp.style.top= (win_size[0]/24*9)+'px';
str_wtmp.style.zIndex = '4';
str_wtmp.style.fontSize=(win_size[0]/8)+"px";
str_otmp.style.right = (counter2+(win_size[0]/12))+'px';
str_otmp.style.top= (win_size[0]/24*9)+'px';
str_otmp.style.zIndex = '4';
str_otmp.style.fontSize=(win_size[0]/8)+"px";
str_opls.style.right = (win_size[0]/12)+'px';
str_opls.style.top= (win_size[0]/24*9)+'px';
str_opls.style.zIndex = '4';
str_opls.style.fontSize=(win_size[0]/8)+"px";
}
//Movement of round meter needle
function mv_analog_bar(){
bar_wtmp.style.left = 0+'px';
bar_wtmp.style.top= 0+'px';
bar_wtmp.style.zIndex = '5';
bar_wtmp.style.webkitTransform = "rotate("+rt_wtmp+"deg)";
bar_otmp.style.left = count_max2+'px';
bar_otmp.style.top= 0+'px';
bar_otmp.style.zIndex = '5';
bar_otmp.style.webkitTransform = "rotate("+rt_otmp+"deg)";
bar_opls.style.left = count_max3+'px';
bar_opls.style.top= 0+'px';
bar_opls.style.zIndex = '5';
bar_opls.style.webkitTransform = "rotate("+rt_opls+"deg)";
}
//For drawing the opening
function draw_data(){
bar_wtmp.style.webkitTransform = "rotate("+rt_wtmp+"deg)";
document.getElementById("str_wtmp").innerHTML = (rt_wtmp/2.25).toFixed(0);
bar_otmp.style.webkitTransform = "rotate("+rt_otmp+"deg)";
document.getElementById("str_otmp").innerHTML = (rt_otmp/1.8).toFixed(0);
bar_opls.style.webkitTransform = "rotate("+rt_opls+"deg)";
document.getElementById("str_opls").innerHTML = (rt_opls/27).toFixed(1);
}
//Panel movement opening
function start_meter(){
if(counter<animaton_counter){
mv_analog_p();
mv_dgital_p();
counter2=counter2+add_counter2;
counter3=counter3+add_counter3;
counter++;
setTimeout('start_meter()',10);
}else{
counter1=count_max1;
counter2=count_max2;
counter3=count_max3;
mv_analog_p();
mv_dgital_p();
mv_dgital_str();
mv_analog_bar();
opening();
}
}
//opening
function opening() {
if( (rt_wtmp!=270) && (turn_flg==0) ){
rt_wtmp+=2;
rt_otmp+=2;
rt_opls+=2;
draw_data();
setTimeout("opening()",10);
}else if( (rt_wtmp==270) && (turn_flg==0) ){
turn_flg=1;
setTimeout("opening()",200);
}else if((rt_wtmp!=0) && (turn_flg==1)){
rt_wtmp-=2;
rt_otmp-=2;
rt_opls-=2;
draw_data();
setTimeout("opening()",10);
}else if ((rt_wtmp==0) && (turn_flg==1)){
turn_flg=0;
setTimeout("mainloop()",15);
}
}
//Read data
function check_data() {
try{
var json_data = JSON.parse(fs.readFileSync(filepath, 'utf8'));
tmp_wtmp1=parseInt(json_data["wtmp"]);
tmp_otmp1=parseInt(json_data["otmp"]);
tmp_opls1=parseInt(json_data["opls"]);
}catch (err){
}
}
//Test check_data()Instead of using it now
function test_data() {
if(turn_flg==0){
tmp_wtmp1++;
tmp_otmp1++;
tmp_opls1++;
}else{
tmp_wtmp1--;
tmp_otmp1--;
tmp_opls1--;
}
if(tmp_wtmp1==100){
turn_flg=1;
}else if(tmp_wtmp1==0){
turn_flg=0;
}
}
//Main loop
function mainloop(){
check_data();
if(tmp_wtmp1!=tmp_wtmp2){
if(tmp_wtmp1 > tmp_wtmp2){
tmp_wtmp2++;
}else{
tmp_wtmp2--;
}
rt_wtmp=tmp_wtmp2*2.25;
bar_wtmp.style.webkitTransform = "rotate("+rt_wtmp+"deg)";
document.getElementById("str_wtmp").innerHTML = tmp_wtmp2 ;
}
if(tmp_otmp1!=tmp_otmp2){
if(tmp_otmp1 > tmp_otmp2){
tmp_otmp2++;
}else{
tmp_otmp2--;
}
rt_otmp=tmp_otmp2*1.8;
bar_otmp.style.webkitTransform = "rotate("+rt_otmp+"deg)";
document.getElementById("str_otmp").innerHTML =tmp_otmp2;
}
if(tmp_opls1!=tmp_opls2){
if(tmp_opls1 > tmp_opls2){
tmp_opls2++;
}else{
tmp_opls2--;
}
rt_opls=tmp_opls2*2.7;
bar_opls.style.webkitTransform = "rotate("+rt_opls+"deg)";
document.getElementById("str_opls").innerHTML =(tmp_opls2/10).toFixed(1);
}
setTimeout("mainloop()",15);
}
window.onload = function(){
start_meter();
}
The following is the previous difference.
arduino.ino
#define WTMP_IN (A0) //water temp
#define OTMP_IN (A1) //oil temp
#define OPLS_IN (A2) //oil press
#define B_LV_IN (A3) //battery level
~~~~~~~~~~~~~~
/get message from pi
void get_message(int n){
~~~~~~~~
}else if((cmd[0] >= 48) && (cmd[0] < 79)) //0x30~0x4F return message state
{
message_state = cmd[0];
}
~~~~~~~~
}
~~~~~~~~~~~~~~
//send message to pi
void send_message(){
//when get cmd switch
switch (message_state) {
~~~~~~~~
//analog read
case 0x31: //water temp upper bit
Wire.write(r_wtmp >> 8);
break;
case 0x32: //water temp low bit
Wire.write(r_wtmp & 0xFF);
break;
case 0x33: //oil temp upper bit
Wire.write(r_otmp >> 8 );
break;
case 0x34: //oil temp low bit
Wire.write(r_otmp & 0xFF);
break;
case 0x35: //oil press upper bit
Wire.write(r_opls >> 8);
break;
case 0x36: //oil press low bit
Wire.write(r_opls & 0xFF);
break;
case 0x37: //battery level upper bit
Wire.write(r_b_lv >> 8);
break;
case 0x38: //battely level low bit
Wire.write(r_b_lv & 0xFF);
break;
~~~~~~~~
}
}
~~~~~~~~~~~~~~
void check_input()
{
switch (read_counter){
case 0:
r_wtmp=analogRead(WTMP_IN);
read_counter++;
break;
case 1:
r_otmp=analogRead(OTMP_IN);
read_counter++;
break;
case 2:
r_opls=analogRead(OPLS_IN);
read_counter++;
break;
case 3:
r_b_lv=analogRead(B_LV_IN);
read_counter++;
break;
case 4:
read_counter=0;
break;
}
}
~~~~~~~~~~~~~~
//main loop
void loop()
{
~~~~~~~~
switch(ino_state)
{
~~~~~~~~
case 0x01: //arduino normal state
if( (acc==0) && (!slp_interbal_flg) )
{
ino_state++; //pi shutdown state
}
//check sleep interbal
else if(slp_interbal_flg)
{
if(counter_switch)
{
if(millis() > onslp_max_time)
{
slp_interbal_flg = false;
}
}
else
{
if( (millis() < onslp_past_time) && (millis() > onslp_max_time) )
{
slp_interbal_flg = false;
}
}
}else
{
check_input();
}
break;
~~~~~~~~
}
arduino_meter.py
import math
~~~~~~~~~~~~~~
#thermistor config
THERM_B=4181
THERM_R1=3.00
THERM_R0=2.3
THERM_T0=298.15
~~~~~~~~~~~~~~
#get thermistor
def get_therm(tmp):
if ( tmp <= 0) | ( tmp > 1023):
TMP = 1
else:
TMP = tmp
temp = 0
rr1 = THERM_R1 * TMP / (1024.0 - TMP)
t = 1 / ( math.log( rr1/THERM_R0 ) / THERM_B + 1/THERM_T0 )
temp = (t - 273.5)
return int(temp)
#get oil_press
def get_oil_press(tmp):
vol = (5000/1023)*tmp
press = (vol-600)/40
return press
~~~~~~~~~~~~~~
#get car data
def get_analog_level(addr,u_data,l_data):
TRY1 = I2C_TRY
TRY2 = I2C_TRY
analog_leve=0
while TRY1:
try:
reading = int(bus.read_byte_data(addr,u_data))
analog_level = reading << 8
except IOError as e:
print "get car data IO error"
TRY1-=1
except :
print "get car date Unexcepted error"
raise
else:
break
if not TRY1:
raise
while TRY2:
try:
reading = int(bus.read_byte_data(addr,l_data))
analog_level = analog_level | reading
return analog_level
except IOError as e:
print "get car data IO error"
TRY2-=1
except :
print "get car date Unexcepted error"
raise
else:
break
if not TRY2:
raise
~~~~~~~~~~~~~~
#write data
def write_data():
m_data = {"wtmp":"" , "otmp":"" ,"opls": ""}
m_data["wtmp"]=get_therm(w_temp)
m_data["otmp"]=get_therm(o_temp)
m_data["opls"]=get_oil_press(o_press)
with open('meter_data.json','w') as f:
json.dump(m_data, f, sort_keys=True, indent=4)
~~~~~~~~~~~~~~
#main loop
while True:
check_state(SLAVE_ADDRESS)
w_temp = get_analog_level(SLAVE_ADDRESS,0x31,0x32)
o_temp = get_analog_level(SLAVE_ADDRESS,0x33,0x34)
o_press = get_analog_level(SLAVE_ADDRESS,0x35,0x36)
b_level = get_analog_level(SLAVE_ADDRESS,0x38,0x38)
write_data()
time.sleep(0.1)
~~~~~~~~~~~~~~
The sensor uses the PK series made by Auto Gauge on the market for both temperature and oil pressure. It doesn't matter what the manufacturer is if you take the data, but since there is data from the previous work, I use it as it is.
Recommended Posts