電源電圧周波数監視3.0(2)

前回の続きで、ソフトウェアを用意していきます。ちなみに公開しているページはこっち

Raspberry Piの準備

Raspberry Pi側はRaspberry Pi OSをMicroSDに書き込んで、普通に立ち上げていきます。Raspberry Pi imagerでmicroSDにRaspberry Pi OS Liteのイメージを書き込みます。書き込んだら、コンソール無しでセットアップを進められるようsshを有効化しておくため

$ cd /media/${USER}/boot/
$ touch ssh

としておきます。

Raspberry PiにmicroSDを挿して起動します。起動したら、

$ ssh pi@raspberrypi.local -o PreferredAuthentications=password

でログインします。(普通は -o 以下はなくてもいい)

$ sudo raspi-config

でraspi-configを起動して、パスワード変更、シリアルポートのログインシェル無効化とシリアルインタフェース有効化、localeでja_JP.UTF-8を追加、hostnameの変更を行います。変更して再起動したら、再度ログインして、

$ sudo apt update
$ sudo apt upgrade

として、更新をかけておきます。

ATmega328pのファームウェアの準備

ホストPC側でArduino Unoとしてファームウェアを用意しておきます。

今回のソースコードは以下のようになりました。

#define TCCCLK 2000000    // CPUクロックを8分周した値。
#define ICP1 8  // ICP1の端子を定義

// 周期測定ののための変数
volatile uint16_t MaxV,MinV,NumV;
volatile uint32_t SumV;
volatile uint16_t CapV;
volatile uint16_t PreCap,NowCap;

// 1秒間の最大最小平均を格納するための変数
uint16_t tMaxV,tMinV,tNumV;
float tAveV;
uint32_t tSumV;

unsigned long current_time;

// 割り込みハンドラ
ISR(TIMER1_CAPT_vect) {
  TIFR1 |= (1<<ICF1); 
  NowCap = ICR1;
  CapV = NowCap - PreCap;       // 差分を求めて周期を算出
  PreCap = NowCap;
  if(CapV > MaxV) MaxV = CapV;
  if(CapV < MinV) MinV = CapV;
  SumV += CapV;
  NumV++;
}

// 割込ごとの電圧測定のための変数
volatile uint32_t Vcnt; // 測定回数
volatile uint16_t Vval; // 測定値読出用
volatile double Vtmp;   // 電圧
volatile double Vsqsum; // 自乗和積算用
volatile double Vmax;   // 電圧最大値
// 1秒間の計測結果を格納するための変数
uint32_t tVcnt;
double tVsqsum;
double tVol;
double tVmax;

// 割り込みハンドラ
ISR(ADC_vect) {
  Vval = (uint16_t)ADCL + ((uint16_t) ADCH << 8); // ADCLを先に読む必要がある。
  Vtmp = ((double)Vval-512.);   // 単位はAD変換値刻み。実電圧への変換はRasPi側で行う
  Vsqsum += Vtmp*Vtmp;
  if(abs(Vtmp) > Vmax) Vmax=abs(Vtmp);
  Vcnt++;
}

void setup()
{
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  
  // TCC1でICP1信号(PB0端子=IO8)の周期を計測する
  TCCR1A = 0; //initialize Timer1
  TCCR1B = 0;
  TCNT1 = 0;
  
  pinMode(ICP1, INPUT_PULLUP);  //ICP1の端子をプルアップあり入力に設定

  TCCR1B =  0x02;   // 16MHzを8分周
  TIMSK1 |= (1 << ICIE1); // キャプチャ割り込み許可

  // ADCで入力電圧の実効値と最大値を測定する
  DIDR0 &= 0xFE;  // ADC0のデジタル入力禁止
  ADMUX = 0x00;   // AREF=外部、入力=ADC0
  ADCSRB = 0;     // ADCをFree running modeで使用
  ADCSRA = 0xEF;  // ADC Enable/ADC Start Conversion/Auto Trigger ENABLE
                  //     Interrupt Enable/Prescaler=128
  current_time = millis();
}

void loop()
{
  static uint8_t skp = 3;   // 最初の何回かはデータを捨てる
  
  if (millis() - current_time >= 1000)
  {
    // 割り込みで更新している変数をコピー&初期化する
    noInterrupts(); //割り込み停止
    tMaxV = MaxV; tMinV = MinV; tSumV = SumV; tNumV = NumV;
    MaxV = 0; MinV = 65535; SumV = 0; NumV = 0;
    tVcnt = Vcnt; tVsqsum = Vsqsum; tVmax = Vmax;
    Vcnt = 0; Vsqsum = 0; Vmax = 0;
    interrupts();   //割り込み再開
    tAveV = (float)tSumV / (float)tNumV;
    tVol  = sqrt(tVsqsum/tVcnt);
    
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    current_time = millis();

    // PCに送信
    if(skp == 0){
      Serial.print((double)TCCCLK/(double)tMaxV*1000.);
      Serial.print(",");
      Serial.print((double)TCCCLK/(double)tMinV*1000.);
      Serial.print(",");
      Serial.print((double)TCCCLK/(double)tAveV*1000.);
      Serial.print(",");
      Serial.print(tVol);
      Serial.print(",");
      Serial.println(tVmax);
    } else {
      skp--;
    }
  }
}

ADCはフリーランニングモードでAD変換させ続けて、割り込みで結果を取得します。確か、1秒間に2000回位の変換回数だったと思います。(忘れました・・・)
AD変換した値はdoubleに型変換して、そのまま絶対値の最大値と自乗平均を取っています。実際の電圧への変換はRaspberry Pi側で行うことで、使用する充電器(というかトランス)が変わってもファームウェアの変更は無しでいけるようにしました。
継ぎ接ぎだらけなので、変数名とかメチャクチャですが、めんどくさいのでそのままにしています。

avrdudeのインストール

$ sudo apt install avrdude tio

でavrdude(と後で使うtio)をインストールします。インストールしたら、/etc/avrdude.confを編集して、

#
programmer
  id    = "linuxgpio";
  desc  = "Use the Linux sysfs interface to bitbang GPIO lines";
  type  = "linuxgpio";
  reset = 8;
  sck   = 11;
  mosi  = 10;
  miso  = 9;
;

という感じでもともとコメントアウトされている行を有効化して、AVRのプログラミングに使用する端子を定義します。ファイルを保存したら、

$ sudo avrdude -c linuxgpio -p m328p

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: safemode: Fuses OK (E:FF, H:D9, L:62)

avrdude done.  Thank you.

$ 

という感じで、ATmega328pにアクセスできることを確認します。

FUSE bitの設定

ATmega328pをArduinoとして動作させるにはhardware/arduino/avr/board.txtの中のArduino Unoのところに書かれたFuse bitの値を設定する必要がありますので、ターミナルモードで設定します。

$ sudo avrdude -c linuxgpio -p m328p -t

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude> w lfuse 0 0xff
>>> w lfuse 0 0xff 

avrdude> w hfuse 0 0xde
>>> w hfuse 0 0xde 

avrdude> w efuse 0 0xfd
>>> w efuse 0 0xfd 

avrdude> q
>>> q 

avrdude: safemode: Fuses OK (E:FD, H:DE, L:FF)

avrdude done.  Thank you.

$ 

Arduinoバイナリの書き込み

ホストマシンのArduino環境でメニューから「スケッチ」⇒「コンパイルしたバイナリを出力」として、バイナリをHEXファイルで出力します。出力したHEXファイルはscpでRaspberry Piへ持ってきておきます。

Raspberry Pi側で「with_bootloader.standard.hex」が付いた方のファイルをATmega328pに書き込みます。

$ sudo avrdude -c linuxgpio -p m328p -u -e -U flash:w:"スケッチ名称.ino.with_bootloader.standard.hex":a

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: reading input file "スケッチ名称.ino.with_bootloader.standard.hex"
avrdude: input file スケッチ名称.ino.with_bootloader.standard.hex auto detected as Intel Hex
avrdude: writing flash (32768 bytes):

Writing | ################################################## | 100% 1.63s

avrdude: 32768 bytes of flash written
avrdude: verifying flash memory against スケッチ名称.ino.with_bootloader.standard.hex:
avrdude: load data flash data from input file スケッチ名称.ino.with_bootloader.standard.hex:
avrdude: input file スケッチ名称.ino.with_bootloader.standard.hex auto detected as Intel Hex
avrdude: input file スケッチ名称.ino.with_bootloader.standard.hex contains 32768 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 1.41s

avrdude: verifying ...
avrdude: 32768 bytes of flash verified

avrdude done.  Thank you.

$ 

完了したら、tioでコンソール出力を確認します。

$ tio -b 115200 /dev/ttyS0 
[tio 18:21:19] tio v1.32
[tio 18:21:19] Press ctrl-t q to quit
[tio 18:21:19] Connected
inf,30518.04,nan,1.59,1.59
...
...

(ここでは入力側のトランスを接続していないので、infとかnanとかが出ています)

コメントを残す

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

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)