忘備録-備忘録

技術的な備忘録

Arduinoシリアルから一行入力

2021-11-12 21:18:08 | arduino
Arduinoのシリアル通信で"\n"まで1行受信するプログラムです。関数loop(){}内で毎回呼び出します。受信していない場合はブロックせずに終了して戻り値が-1になります。また、"\n"まで受信していない場合も戻り値-1で終了します。

プログラム
#include <errno.h>

void setup()
{
  Serial.begin(115200);
  while (!Serial);
}

void loop()
{
  int cmd;

  if (Serial.available() > 0) {   // 受信したデータが存在する
    int rdata = receiveCmd();     // コマンドを受信
    if (rdata != -1) cmd = rdata; // -1 受信中 or 受信エラー
  }

  delay(100);
}

int receiveCmd(void)
{
  int cmd = -1;           // -1 受信中 or 受信エラー
  static int recptr = 0;  //受信した文字数を保存する
  static char recv[32];   //受信した文字列を保存する

  while (1) {             //すべての受信データを受け取る
    int receive = Serial.read();
    if (receive == -1) break;        //受信データなし ループを抜ける
    recv[recptr] = receive;
    if ((recv[recptr] == '\n') || (recv[recptr] == '\r')) {
      recv[recptr] = '\0';
      recptr = 0;
      char *ptr;
      long rcvdata = strtol(recv, &ptr, 10); //文字列を整数に変換
      if (recv[0] == '\0') break;            //空行
      if (errno != 0  )  break;              //エラー発生
      if (*ptr != '\0')  break;              //エラー発生
      cmd = rcvdata;
    } else {
      recptr++;
      if (recptr > 30) recptr = 0;           //バッファーオーバーフロー対策
    }
  }
  return cmd;
}


ESP32でインプットキャプチャ

2021-11-11 18:43:35 | arduino
ESP32マイコンを使いインプットキャプチャ機能を使ってみました。

ソースコード
#include "driver/mcpwm.h"

void setup() {
  Serial.begin(115200);
  delay(500);
  mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, 37);
  mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, MCPWM_POS_EDGE, 0); 
}

void loop() {
  static unsigned int old = 0;
  unsigned int number1 =  mcpwm_capture_signal_get_value(MCPWM_UNIT_0,MCPWM_SELECT_CAP0);
  if(old != number1) {
    Serial.print(number1);
    Serial.print("   ");
    Serial.println(number1 - old);
    old = number1;
  }
  delay(10);
}	

解説
インクルードファイル
#include "driver/mcpwm.h"
が必要です。
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, 37);
でインプットキャプチャに使うピンをしてします。この例ではタイマユニット0番のキャプチャピン0番をGPIO37で回路に接続することになります。MCPWM_UNIT_は0,1の2つMCPWM_CAP_は0,1,2の3つ合計6つ指定できます。
mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, MCPWM_POS_EDGE, 0);
でキャプチャの設定と起動を行います。MCPWM_POS_EDGEは起動するタイミングの設定です。最後の0は指定した回数、信号が入力するまでキャプチャを行いません。0で1回の入力でキャプチャになります。

インプットキャプチャ割り込みルーチンも自作することができます。

ソースコード
#include "driver/mcpwm.h"

volatile unsigned int input_capture_data = 0; 
bool input_capture_call_back(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata, void *user_data)
{
  static unsigned int old_number = 0;
  unsigned int number =  edata->cap_value;
  input_capture_data = number - old_number;
  old_number = number;
  return false;
}

void setup() {
  mcpwm_capture_config_t input_capture_setup;
  input_capture_setup.cap_edge = MCPWM_NEG_EDGE;
  input_capture_setup.cap_prescale = 1;
  input_capture_setup.capture_cb = input_capture_call_back;
  input_capture_setup.user_data = NULL;
  
  Serial.begin(115200);
  mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, 37);
  mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0,&input_capture_setup ); 
}

void loop() {
  static unsigned int old_data = 0;
  if( old_data != input_capture_data ) {
    Serial.println(input_capture_data);
    old_data = input_capture_data;
  }
  delay(1);
}

参考サイト

BME280センサを使用した温湿度気圧計

2017-08-09 19:19:00 | arduino

BME280センサを使用した温湿度気圧計を製作しました。マイコンにはATMEGA168をArduino化して使用しています。

DSC_0199_3

回路図

7セグメントLEDを12桁も使用するためピン数が足りず、7セグメントドライバに74HC4511を使用しました。

image

プログラム

センサのBME280を扱うライブラリはここのものを使用しました。

一部ATMEGA特有の表記を使用しています。ATMEGA168かATMEGA328でないと動作しません。

/*
 * 気温・湿度・気圧計
 * BME280センサーを使用(I2Cモード)
 * 
 * PD0-PD3 出力する数字
 * PD4    小数点
 * PD5-PD7,PB0 7セグメントLED1
 * PB1-PB4   7セグメントLED2
 * PC0-PC3     7セグメントLED3
 */
#include <BME280.h>
#include <MsTimer2.h>

#define SERIAL_BAUD 9600

BME280 bme(1,1,1,3,5,0,false,0x76); 
bool metric = true;
unsigned char LED7seg[3][5];

void printBME280Data(Stream * client);
void printBME280CalculatedData(Stream* client);

void display_numbers (void)
{
  static int display_line = 0;
  int led = display_line / 4;
  int disp = display_line % 4;

  PORTB = PORTC = PORTD = 0;
  PORTD = LED7seg[led][disp];
  if(LED7seg[led][4]==disp) {
    PORTD |= 0x10; 
  }
  switch(display_line)
  {
    case 0:
    PORTD |= 0x20;
    break;
    case 1:
    PORTD |= 0x40;
    break;
    case 2:
    PORTD |= 0x80;
    break;
    case 3:
    PORTB |= 0x01;
    break;
    case 4:
    PORTB |= 0x02;
    break;
    case 5:
    PORTB |= 0x04;
    break;
    case 6:
    PORTB |= 0x08;
    break;
    case 7:
    PORTB |= 0x10;
    break;
    case 8:
    PORTC |= 0x01;
    break;
    case 9:
    PORTC |= 0x02;
    break;
    case 10:
    PORTC |= 0x04;
    break;
    case 11:
    PORTC |= 0x08;
    break;
  }
  display_line++;
  if(display_line==12) display_line = 0;
}

void setup() {
  DDRD = 0xFF;
  DDRB = 0x1F;
  DDRC = 0x0F;
  for(int i=0;i<3;i++) {
    LED7seg[i][0] = LED7seg[i][1] = LED7seg[i][2] = LED7seg[i][3] = LED7seg[i][4] = 0;
  }
  MsTimer2::set(1, display_numbers);
  MsTimer2::start();
  while (!bme.begin()) {
    delay(1000);
  }
}

void loop() {
  float temp(NAN), hum(NAN), pres(NAN);
  bme.ReadData(pres, temp, hum, true, 1); 

  LED7seg[2][0] = ((int)temp) / 10;
  LED7seg[2][1] = ((int)temp) % 10;
  LED7seg[2][2] = ((int)(temp*10.0)) % 10;
  LED7seg[2][3] = ((int)(temp*100.0)) % 10;
  LED7seg[2][4] = 1;

  LED7seg[0][0] = ((int)hum) / 10;
  LED7seg[0][1] = ((int)hum) % 10;
  LED7seg[0][2] = ((int)(hum*10.0)) % 10;
  LED7seg[0][3] = ((int)(hum*100.0)) % 10;
  LED7seg[0][4] = 1;

  LED7seg[1][0] = ((int)pres) / 1000;
  LED7seg[1][1] = ((int)pres)/100 % 10;
  LED7seg[1][2] = ((int)pres)/10 % 10;
  LED7seg[1][3] = ((int)pres) % 10;
  LED7seg[1][4] = 3;
  delay(1000);
}

binbono arduino互換機を作る

2015-12-04 17:31:43 | arduino
マイコンはarduinoをよく使用します。本体を使いまわせば良いのですが、何かの機器に組み込む場合、1台あたりの値段が結構かかります。AVRマイコン自身は安価なので、なるべく安く組み込めるように考えてみました。

書き込み器とマイコンを分け、マイコン部分を少ない部品で作ることとしました。

マイコン部回路


これだけシンプルになりました。水晶振動子を使用していないのでクロックは内臓の8MHzとなります。また、電源電圧は2.7V~5Vの間で自由に使えます。

書き込み器回路図


マイコン部をシンプルにしたために書き込み器に細かい回路が来ています。書き込み器は使いまわしがきくので問題ないでしょう。ピン配置はaitendoで取り扱っているUSB-TTL変換キットと同じにしました。このキットでも書き込みできると思います。

使用時の写真



ブートローダーの設定
ATmega168  ATmegaBOOT_168_pro_8MHz.hex arduinoをインストールしたフォルダの中にあります。
       ヒューズビット EXTENDED:0xF8  HIGHT:0xFD  LOW:0xE2  LOCKBIT:0xCF

ATmega328  ATmegaBOOT_168_atmega328_pro_8MHz.hex arduinoをインストールしたフォルダの中にあります。
       ヒューズビット EXTENDED:0xFD  HIGHT:0xDA  LOW:0xE2  LOCKBIT:0xCF

IDEでの設定
 IDE上ではArduino Pro or Pro Miniを選びます。



参考サイト
  Arduinoのヒューズ設定
  あちゃんでいいの