Top
Raspberry Pi Pico - 2024年4月16日更新

Arduino(earlephilhower/arduino-pico)を使って開発しています。
ここでは作成したコードを公開しています。
※最新情報や一部のソースはX(twitter) @inunyannで公開しています。ソースは画像になっていますが…
Amazonのほしいものリスト🎁お願いします!!

試作例:かわいい(かわいい)
試作例:LEDキューブ、USBメモリGPIO制御
BOOTSELボタンの活用


●試作例:かわいい(かわいい)

#include "LittleFS.h"
// [Ctrl] + [Shift] + [P], then "Upload LittleFS to Pico/ESP8266".

#include "LovyanGFX.hpp"
#include "lgfxST7735Sspi.h"
static LGFX lcd;

#define PIC_FILE   "/pic##.jpg" // for 7735S(80x160)
#define PIC_NUM_MIN   1
#define PIC_NUM_MAX  24
uint8_t nowPic = PIC_NUM_MIN;

uint8_t btnPressed = 0;

void setup() {
  LittleFS.begin();
  lcd.init();
  pinMode(22, OUTPUT);
  digitalWrite(22, HIGH);
  showPic(nowPic);
}

void setup1() {}

void loop() {
  chkButton();
  delay(10);
}

void loop1() {
  if (btnPressed) {
    if (++nowPic > PIC_NUM_MAX) nowPic = PIC_NUM_MIN;
    showPic(nowPic);
    btnPressed = 0;
  }
  delay(10);
}

void showPic(uint8_t n) {
  if (n < PIC_NUM_MIN || PIC_NUM_MAX < n) return;
  char picFileName[] = PIC_FILE;
  char pinNum[3];
  snprintf(pinNum, sizeof(pinNum), "%02d", n);
  char *ptr = picFileName;
  if (ptr = strstr(ptr, "##")) memcpy(ptr, pinNum, 2);
  if (!LittleFS.exists(picFileName)) return;

  File jpgFile = LittleFS.open(picFileName, "r");
  size_t size = jpgFile.size();
  char *_buf = (char *)malloc(size);
  if (_buf) {
    jpgFile.readBytes(_buf, size);
    lcd.drawJpg((uint8_t *)_buf, size, 0, 0, 0, 0, 0, 0, lgfx::v1::jpeg_div::jpeg_div_t::JPEG_DIV_NONE);
  }
  free(_buf);
  jpgFile.close();
}

void chkButton() {
  uint8_t c = 0;
  while (BOOTSEL) if (!++c) rp2040.reboot(); else delay(10);
  if (c && (btnPressed = 1) && c > 30) rp2040.reboot();
}

class LGFX : public lgfx::LGFX_Device {
  lgfx::Panel_ST7735S _panel_instance;
  lgfx::Bus_SPI       _bus_instance;

public:
  LGFX(void) {
    {
      auto cfg = _bus_instance.config();
      cfg.spi_host = 0;
      cfg.spi_mode = 0;
      cfg.freq_write = 40000000;
      cfg.freq_read  = 20000000;
      cfg.pin_sclk = 18;
      cfg.pin_mosi = 19;
      cfg.pin_miso = -1;
      cfg.pin_dc   = 21;
      _bus_instance.config(cfg);
      _panel_instance.setBus(&_bus_instance);
    }
    {
      auto cfg = _panel_instance.config();
      cfg.pin_cs   =  5;
      cfg.pin_rst  = 20;
      cfg.pin_busy = -1;
      cfg.panel_width  = 80;
      cfg.panel_height = 160;
      cfg.offset_x = 26;
      cfg.offset_y = 1;
      cfg.offset_rotation = 1;
      cfg.dummy_read_pixel = 8;
      cfg.dummy_read_bits = 1;
      cfg.readable = true;
      cfg.invert = true;
      cfg.rgb_order = false;
      cfg.dlen_16bit = false;
      cfg.bus_shared = false;
      _panel_instance.config(cfg);
    }
    setPanel(&_panel_instance);
  }
};

●試作例:LEDキューブ、USBメモリGPIO制御

#include "Adafruit_TinyUSB.h"

#define DISK_BLOCK_NUM  16
#define DISK_BLOCK_SIZE 512
#include "ramdisk.h"

Adafruit_USBD_MSC usb_msc;

void setup() {
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
  TinyUSB_Device_Init(0);
#endif

  for (uint32_t i = 0; i < 30; i++) gpio_init(i);

  usb_msc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
  usb_msc.setReadWriteCallback(msc_read_callback, msc_write_callback, msc_flush_callback);
  usb_msc.setUnitReady(true);

  usb_msc.begin();
}

void loop() {
}

int32_t msc_read_callback(uint32_t lba, void* buffer, uint32_t bufsize) {
  if (lba == 3) get_gpio_status();

  uint8_t const* addr = msc_disk[lba];
  memcpy(buffer, addr, bufsize);

  return bufsize;
}

int32_t msc_write_callback(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
  uint8_t* addr = msc_disk[lba];
  memcpy(addr, buffer, bufsize);

  if (lba == 3) set_gpio_status();

  return bufsize;
}

void msc_flush_callback() { }

void get_gpio_status() {
  for (uint32_t i = 0; i < 30; i++) {
    msc_disk[3][     i] = gpio_get(i)          ? '1' : '0';
    msc_disk[3][37 + i] = gpio_get_dir(i)      ? 'o' : 'i';
    msc_disk[3][74 + i] = gpio_is_pulled_up(i) ? 'u' : gpio_is_pulled_down(i) ? 'd' : '-';
  }
}

void set_gpio_status() {
  for (uint32_t i = 0; i < 30; i++) {
    gpio_set_dir(i, msc_disk[3][37 + i] == 'o');
    if      (msc_disk[3][74 + i] == 'u') gpio_pull_up(i);
    else if (msc_disk[3][74 + i] == 'd') gpio_pull_down(i);
    else gpio_disable_pulls(i);
    gpio_put(i, msc_disk[3][i] == '1');
  }
}

using System;
using System.IO;

public class GpioReader {
 public static void Main() {
  FileOptions FileFlagNoBuffering = (FileOptions)0x20000000; // FILE_FLAG_NO_BUFFERING
  using(FileStream fs = new FileStream(Environment.GetEnvironmentVariable("GPIO_BAT_BASENAME") + ".txt", FileMode.Open, FileAccess.Read, FileShare.Read, 512, FileFlagNoBuffering | FileOptions.Asynchronous & FileOptions.SequentialScan)) {
   using(StreamReader sr = new StreamReader(fs)) {
    string gpio = sr.ReadToEnd();
    Console.WriteLine(gpio);
   }
  }
 }
}

●BOOTSELボタンの活用
・短く(300ms未満)押すとボタン入力(btnPressed)
・長めに(300ms以上)押すとリセット
・押し続ける(3秒以上)とBOOTSELモードで起動
※FreeRTOSを使っていますが、”while (true)”を外せばFreeRTOSを使用していなくても利用可能です。

#include "FreeRTOS.h"

uint8_t btnPressed = 0;

void setup() {
  xTaskCreate(chkButton, "btn", configMINIMAL_STACK_SIZE, nullptr, 0, nullptr);
}

void loop() {
  if (btnPressed) {
    // ボタン押された時の処理
    btnPressed = 0;
  }
}

void chkButton(void *p) {
  while (true) {
    uint8_t c = 0;
    while (BOOTSEL) {
      if (!++c) rp2040.reboot();
      delay(10);
    }
    if (c > 30) rp2040.reboot();
    if (c) btnPressed = 1;
    delay(10);
  }
}


ibunyan.com