Spresense ソースコードその4(装置制御)

測定した気温を元にヒーターやクーラーの制御を行います。実装した機能は

  1. GNSS受信機を活かして月ごとの温度上限と下限の設定
  2. 気温急変検知及び急変検知時の動作(早めに温め/冷却)

GNSS受信機から得られる時間情報は国際標準時なので日本時間と9時間の誤差があります。しかしNuttxに時差補正するオブジェクトが見つからなかったのですが、どうせ月ごとの設定では誤差の範囲なので気にするのをやめました。温度の急変は1時間前、3分前、現在の比較を行い、1時間前より2℃以上変化し3分前より2℃以上変化していない(温度センサーを手で持っている状態を想定)ときに気温下降時はヒーターの動作点を1℃上げ、気温上昇時はクーラーの動作点を1℃下げることで水温の急変の抑制を狙っています。

#include <sdk/config.h>
#include <stdio.h>
#include <arch/board/board.h>
#include <arch/chip/pin.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <errno.h>
#include “cntunit.h”

int h1flg = 0, h2flg = 0,fnflg = 0;
int ht_boost = 0;
int fn_boost = 0;


void* cntunit(void *arg)
{
board_gpio_config(PIN_PWM1, 0, 0, 0, 0); //D05 ヒーター制御
board_gpio_config(PIN_PWM0, 0, 0, 0, 0); //D06 ファン制御
board_gpio_config(PIN_SPI3_CS1_X, 0, 0, 0, 0); //D07 追加ヒーター制御

floattemp_hv = 0;
floattemp_fv = 0;
floattemp_hv2 = 0;
intd_mon = 0;
intptcnt = 10;

while(1){
if(hold_flg == 0) //制御本体
{
if(gnss_flg < 1){
d_mon = 0;
}
else{
d_mon = gn_month;
}

 
if(ptcnt < 0){
printf(“Date %d/%d/%d Time(GMT) %d:%d:%d\n”,gn_year,gn_month,gn_day,gn_hour,gn_minute,gn_sec);
printf(“Heater temp:%3.1f, error- crent:%d, avgerr:%d\n”,temp_h,heat_err,heat_avgerr);
printf(“Water temp:%3.1f, error- crent:%d, avgerr:%d\n”,temp_w,wtr_err,wtr_avgerr);
printf(“Air temp-crent:%3.1f,avg 1min:%3.1f, 2min:%3.1f, 10min%3.1f, 60min%3.1f\n”,temp_a,temp_a0[0],temp_a0[2],temp_a0[10],temp_a0[59]);
printf(“Air error- crent:%d, avgerr:%d\n”,air_crnterr,air_err);
printf(“SET-heat1:%3.1f,SET-heat2:%3.1f,SET-cool:%3.1f\n”,temp_hv,temp_hv2,temp_fv);
printf(“htbst:%d,heat1:%d,fnbst:%d,fan:%d,heat2:%d,GNSS:%d\n\n”,ht_boost,h1flg,fn_boost,fnflg,h2flg,gnss_flg);
ptcnt = 30;
}else{
ptcnt –;
}

// ヒーター動作点決定 //
if((temp_a0[shour-1]-temp_a0[0])>2) //温度急下降判定
{
if((temp_a0[shour/12]-temp_a0[0])<2)
{
ht_boost = 1;
}
else{
ht_boost = 0;
}
}
else
{
ht_boost = 0;
}

if(temp_hvt > vtemp_hmax[d_mon]){ //動作温度算出
temp_hv = vtemp_hmax[d_mon];
}
elseif(temp_hvt < vtemp_hmin[d_mon]){
temp_hv = vtemp_hmin[d_mon];
}
else{
temp_hv = temp_hvt;
}
 
if(ht_boost == 1) //気温急下降時は動作点を1℃上げる
{
temp_hv++;
}

if(emstp == 1) //非常停止処理
{
board_gpio_write(PIN_PWM1, 0);
board_gpio_write(PIN_PWM0, 0);
board_gpio_write(PIN_SPI3_CS1_X, 0);
break;
}

if(heat_err < 1)
{
if(temp_h < (temp_hv – 0.2)){ //ヒーター制御
board_gpio_write(PIN_PWM1, 1);
h1flg = 1;
}
elseif(temp_h > temp_hv){
board_gpio_write(PIN_PWM1, 0);
h1flg = 0;
} else{ } // ON/OFF動作点間は何もしない
} else{
board_gpio_write(PIN_PWM1, 0);
h1flg = 0;
}

// ファン動作点決定 //
if((temp_a0[0]-temp_a0[shour-1])>2) //温度急上昇判定
{
if((temp_a0[0]-temp_a0[3])<2)
{
fn_boost = 1;
}
else
{
fn_boost = 0;
}
}
else
{
fn_boost = 0;
}

if(temp_fvt > vtemp_wmax[d_mon]){ //ファン動作点算出
temp_fv = vtemp_wmax[d_mon];
}
elseif(temp_fvt < vtemp_wmin[d_mon]){
temp_fv = vtemp_wmin[d_mon];
}
else{
temp_fv = temp_fvt;
}
 
if(fn_boost == 1) //温度急上昇中はファン動作点を1℃下げる
{
temp_fv–;
}

if(wtr_err < 1)
{
if(temp_w > temp_fv) //ファン制御
{
board_gpio_write(PIN_PWM0, 1);
fnflg = 1;
}
elseif(temp_w < (temp_fv – 0.5))
{
board_gpio_write(PIN_PWM0, 0);
fnflg = 0;
} else{ } // ON/OFF動作点間は何もしない
}else{
board_gpio_write(PIN_PWM0, 0);
fnflg = 0;
}

// 凍結防止ヒーター //

if((temp_hvt – 2) > vtemp_h2max[d_mon]) //動作温度範囲に当てはめる
{
temp_hv2 = vtemp_h2max[d_mon];
} else if((temp_hvt – 2 < vtemp_h2min[d_mon]))
{
temp_hv2 = vtemp_h2min[d_mon];
} else
{
temp_hv2 = (temp_hvt – 2);
}

if(wtr_err < 1){
if(temp_w < (temp_hv2 – 0.4)) //ヒーター制御
{
board_gpio_write(PIN_SPI3_CS1_X, 1);
h2flg = 1;
} else if(temp_w > temp_hv2)
{
board_gpio_write(PIN_SPI3_CS1_X, 0);
h2flg = 0;
} else{ } // ON/OFF動作点間は何もしない
}else{
board_gpio_write(PIN_SPI3_CS1_X, 0);
h2flg = 0;
}

if(emstp == 1) //非常停止処理
{
board_gpio_write(PIN_PWM1, 0);
board_gpio_write(PIN_PWM0, 0);
board_gpio_write(PIN_SPI3_CS1_X, 0);
break;
}
}else
{
board_gpio_write(PIN_PWM1, 0); //各ポート出力停止
board_gpio_write(PIN_PWM0, 0);
board_gpio_write(PIN_SPI3_CS1_X, 0);
}

if(emstp == 1) //非常停止処理
{
board_gpio_write(PIN_PWM1, 0);
board_gpio_write(PIN_PWM0, 0);
board_gpio_write(PIN_SPI3_CS1_X, 0);
break;
}

sleep(1);

}
returnNULL;
}

同様にヘッダファイル

#ifndef _INCLUDE_CONTUNIT_
#define _INCLUDE_CONTUNIT_
void* cntunit(void *arg);
#endif

int intvlh; //ヒーター測定、判定間隔(秒単位)
int intvla; //水温、気温判定間隔(秒単位)
int sintv; //水温、気温測定間隔(秒単位、2秒以上)
int shour, sday, sweek; //各時間間隔ごとの気温計測数

float vtemp_hmax[13]; //月別ヒーター温度上限(ここを越えたら絶対に止める)
float vtemp_hmin[13]; //月別ヒーター温度下限(ここを下回ったら絶対に動かす)
float vtemp_wmax[13]; //月別ファン動作制御温度上限
float vtemp_wmin[13]; //月別ファン動作制御温度下限
float vtemp_h2max[13]; //月別追加ヒーター制御上限
float vtemp_h2min[13]; //月別追加ヒーター制御下限

//時刻情報//
int gn_year;
int gn_month;
int gn_day;
int gn_hour;
int gn_minute;
int gn_sec;
int gnss_flg;

float temp_h; //ヒーター温度
int heat_err; //ヒーター測定エラー
int heat_avgerr; //ヒーター測定1分値エラー
int wtr_err; //水温測定エラー
int wtr_avgerr; //水温1分値エラー
int air_err; //気温測定エラー
int air_crnterr;
float temp_w; //水温
float temp_a; //気温生データ
float temp_a0[60]; //1時間まで1分ごとの気温
float temp_hvt; //直近一週間から算出したヒーター動作点
float temp_fvt; //直近一週間から算出したファン動作点
int emstp; //非常停止フラグ
int h1flg, h2flg, fnflg; //表示用フラグ
int hold_flg; //一時停止フラグ
int ht_boost; //気温急低下フラグ
int fn_boost; //気温急上昇フラグ
int gnss_flg; //時刻情報取得フラグ
This entry was posted in プログラミング, ベランダビオトープ, 園芸, 睡蓮水槽管理装置, 電子工作 and tagged , , , . Bookmark the permalink.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA