fenri's diary

基本的には勉強し始めたC#のメモ。後は140字で収まらない駄文。

KP-DRV8830がM5 StickCで動いた

共立エレショップで買ったKP-DRV8830がうまくいかない。。。

調べた限りの事はやったつもりだけどなんでかうまくいかない。
うーん。。。

動いた!
わかってみれば超アホなことで
モータードライバに渡している値が小さすぎて電圧低くて回らないっていう。。。

そりゃそーだよ。
今回助言いただいた皆様ありがとうございました。


参考にしたとこ
kirakulabo.blogspot.com
shintarof.hatenablog.com
lang-ship.com


上記のブログの回路図上の4.7Kの抵抗は手持ちがなかったので
10Kの抵抗にしてみた。

KP-DRV8830の3ピンをM5StickCのG0へ
4ピンをG26に接続
KP-DRV8830の8ピンと9ピンをタミヤのモーターに接続

何が違うのか。。。

#include <M5StickC.h>

void writeRegister(byte adr, byte vset,byte Hbridge){//vset 電圧設定 データシートp10、Hbridge = 0x01;//回転方向(ブリッジ制御) データシートp8 0x01 正転 0x02逆転
  Wire.beginTransmission(adr);//I2Cの初期設定 データシートp12
  Wire.write(0x00);//スタンバイ データシートp8
  int vdata = (vset << 2) + Hbridge;   //DRV8830に送る信号 データシートp13 D0-1 Hブリッジ D2-D7 
  Wire.write(vdata);
  Wire.endTransmission();
}
void setup() {
  Serial.begin(115200);
  Wire.begin(0, 26); //SDA, SCL
  Wire.setClock(50000);
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.setTextSize(2);
}

void loop() {
  M5.update();
  if(M5.BtnA.pressedFor(100)){
     M5.Lcd.setCursor(10,10);
     M5.Lcd.println("start");
     writeRegister(0x63,0x30,0x01);//(正転)
     writeRegister(0x65,0x30,0x01);//(正転)
     delay(10);
  }else{
     M5.Lcd.setCursor(10,10);
     M5.Lcd.println("stop ");
     writeRegister(0x63,0x00,0x03);//vset:0x00 Hbridg:0x03(ブレーキ)
     writeRegister(0x65,0x00,0x03);//vset:0x00 Hbridg:0x03(ブレーキ)
     delay(10);
  }
}

M5 Stack のbitmapの拡大表示

元は24bitのbitmapを16bitに変換して表示してるっぽい。

padding部分はとりあえずそのまま。

void M5Display::drawBmpFile2(fs::FS &fs, const char *path, uint16_t x, uint16_t y) {
  if ((x >= width()) || (y >= height())) return;

  // Open requested file on SD card
  File bmpFS = fs.open(path, "r");

  if (!bmpFS) {
    Serial.print("File not found");
    return;
  }

  uint32_t seekOffset;
  uint16_t w, h, row, col;
  uint8_t  r, g, b;

  uint32_t startTime = millis();

  if (read16(bmpFS) == 0x4D42) {
    read32(bmpFS);
    read32(bmpFS);
    seekOffset = read32(bmpFS);
    read32(bmpFS);
    w = read32(bmpFS);
    h = read32(bmpFS);

    if ((read16(bmpFS) == 1) && (read16(bmpFS) == 24) && (read32(bmpFS) == 0)) {
      y += h*SCALE - 1;

      setSwapBytes(true);
      bmpFS.seek(seekOffset);

      uint16_t padding = (4 - ((w * 3) & 3)) & 3;
      uint8_t lineBuffer[w * 3 + padding];
      uint8_t lineBuffer2[w * 3 * SCALE + padding];

      for (row = 0; row < h; row++) {
        bmpFS.read(lineBuffer, sizeof(lineBuffer));
        uint8_t*  bptr = lineBuffer;
        uint16_t* tptr = (uint16_t*)lineBuffer2;
        // Convert 24 to 16 bit colours
        for (col = 0; col < w; col++) {
          b = *bptr++;
          g = *bptr++;
          r = *bptr++;
        	for(int i = 0; i < SCALE; i++){
        		*tptr++ = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
        	}
        }

        // Push the pixel row to screen, pushImage will crop the line if needed
        // y is decremented as the BMP image is drawn bottom up
        	for(int i = 0; i < SCALE; i++){
      			pushImage(x, y--, w*SCALE, 1, (uint16_t*)lineBuffer2);
      		}
      }
      Serial.print("Loaded in "); Serial.print(millis() - startTime);
      Serial.println(" ms");
    }
    else Serial.println("BMP format not recognized.");
  }
  bmpFS.close();
}

M5 Stack ボタンの位置

だいたいの位置

#include <M5Stack.h>

void setup() {
  M5.begin();//M5StickCオブジェクトを初期化
  delay(20);

  // 左ボタン ボタンA
  M5.Lcd.drawFastVLine(160 - 90 - 1, 0, 240, RED);

  // 中央ボタン ボタンB
  M5.Lcd.drawFastVLine(160 - 1, 0, 240, GREEN);

  // 右ボタン ボタンC
  M5.Lcd.drawFastVLine(160 + 90 - 1, 0, 240, BLUE);
}

void loop() {
}

ポインタ関連のメモ

ポインタの場合、先頭アドレスは変数で自由に書き換えができますが、配列名の示す先頭アドレスは書き換えができない

www.mgo-tec.com



char* c1;
c1 = "abcdefg";

ダブルクォーテーションで囲んだ文字列は、コンパイラが文字列をメモリ上の書き換え不可の特別な記憶領域に定数として格納し、
そのポインタの先頭アドレスを返している

char c2[8] = “abcdefg”;

配列の初期化の場合は一文字ずつ読み書き可能なメモリ領域へ格納して、最後に ’\0’ を付加します。


●初期化と、型宣言後の代入は、プロセスが異なる。
●ダブルクォーテーション囲み文字列(文字列リテラル)は基本的に書き換えできない領域に記憶され、そのポインタ先頭アドレスを返す。
●配列名は先頭要素アドレスを返すだけで、ポインタのようにアドレス書き換えはできない。

Arudinoのシリアルバッファサイズについて

Arduinoのシリアルのバッファサイズは64Byte もしくは16Byteらしい
なので、むやみにWaitしてデータが全部出てくるまで待つと溢れて受信できないかもしれないし
Waitしてなくてもあふれるかもしれないので注意が必要

Arduino変換あれこれ

文字列から数値

String str = "10";
int i;
float f;

i = str.toInt();
f = str.toFloat();


数値から文字

int  i = 10;
String strH = String(i, HEX); // 数値をHexに変換し文字列に変換
String strD = String(i); // 数値をDecに変換し文字列に変換
String strB = String(i,BIN); // 数値をBinに変換し文字列に変換

RTC使い方

DS3232RTC.h
使い方

RTLとArduino pro miniを接続
SCL SCL(A5)
SDA SDA(A4)
SQW  INT0(pin2) プルアップ抵抗で常時Highに。

割込がかかるとLOWになる

秒単位の指定をする場合は、ALM1
ALM2は分単位

GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

割込の中の処理はできるだけ軽く


void setup(void)
{
  //clear all
  RTC.alarmInterrupt(1, false);
  RTC.alarmInterrupt(2, false);
  RTC.oscStopped(true);

  //sync time with RTC module
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  Serial.flush();

  //show current time, sync with 0 second
  digitalClockDisplay();

  //  synctozero();

  //set alarm to fire every minute
  RTC.alarm(1);
  delay(100);

 //INT0の割込(FALLING High→Low)で、alcallを呼ぶ
  attachInterrupt(0, alcall, FALLING);

  //void setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate);
  //void setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate);
  RTC.setAlarm(ALM1_MATCH_MINUTES, 30, 0, 0, 0);

  RTC.alarmInterrupt(1, true);

  digitalClockDisplay();
  Serial.println("setup end");
  Serial.flush();

}

void loop(void)
{
  Serial.println("loop");
  Serial.flush();

  //process clock display and clear interrupt flag as needed
  if (rtcint) {
    rtcint = false;
    digitalClockDisplay();
    RTC.alarm(1);
  }

  //go to power save mode
  enterSleep();
}

void synctozero() {
  //wait until second reaches 0
  while (second() != 0) {
    delay(100);
  }
}

void alcall() {
  //per minute interrupt call
  Serial.println("alcall");
  Serial.flush();
  rtcint = true;
}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  setSyncProvider(RTC.get); //sync time with RTC
  Serial.print(year());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
  Serial.flush();
}

void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void enterSleep(void)
{
  //enter sleep mode to save power
  Serial.println("Sleep Start");
  Serial.flush();

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();

  sleep_disable();
  power_all_enable();
}