このライブラリはArduino実用入門のESP8266ライブラリより簡便だった
ゼロからよくわかるArduino電子工作入門 改定2版
このライブラリはArduino実用入門のESP8266ライブラリより簡便だった
ゼロからよくわかるArduino電子工作入門 改定2版
家のネットがあれなんでスマホのテザリングをつかった
package main
import (
"machine"
"strconv"
"time"
)
const (
ssid = "HUAWEI@nova@lite@3+"
password = "99991111"
)
// UARTからデータが返ってくるのを待って読み込む関数
func sendATCommand(uart *machine.UART, cmd string, timeout time.Duration) string {
println("送信:", cmd)
uart.Write([]byte(cmd + "\r\n"))
// 応答を待つ
start := time.Now()
var response []byte
buf := make([]byte, 64)
for time.Since(start) < timeout {
if uart.Buffered() > 0 {
n, _ := uart.Read(buf)
response = append(response, buf[:n]...) //
resStr := string(response)
if hasSubstring(resStr, "OK\r\n") || hasSubstring(resStr, "ERROR\r\n") {
break
}
}
time.Sleep(10 * time.Millisecond)
}
return string(response)
}
// 簡易文字列含まれるか判定
func hasSubstring(s, sub string) bool {
if len(sub) == 0 {
return true
}
for i := 0; i <= len(s)-len(sub); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
}
func main() {
time.Sleep(3 * time.Second)
println("\n--- TinyGo ESPAT Direct AT Command Control ---")
// 1. UART1の初期化 (配線: GP4=TX, GP5=RX)
uart := machine.UART1
err := uart.Configure(machine.UARTConfig{
BaudRate: 115200,
TX: machine.GP4,
RX: machine.GP5,
})
if err != nil {
println("UART初期化失敗")
return
}
// 2. モジュールの生存確認
println("\n[1/4] 生存確認中...")
res := sendATCommand(uart, "AT", 1*time.Second)
println("応答:\n", res)
// 3. Wi-Fiモードを「Station」に設定
println("\n[2/4] Wi-Fiモード設定中...")
res = sendATCommand(uart, "AT+CWMODE=1", 1*time.Second)
println("応答:\n", res)
// 4. アクセスポイントに接続
println("\n[3/4] Wi-Fiアクセスポイントに接続中...")
joinCmd := `AT+CWJAP="` + ssid + `","` + password + `"`
res = sendATCommand(uart, joinCmd, 10*time.Second)
println("応答:\n", res)
// 5. TCP接続を確立 (example.com)
println("\n[4/4] TCP接続テスト (example.com)...")
res = sendATCommand(uart, `AT+CIPSTART="TCP","example.com",80`, 3*time.Second)
println("応答:\n", res)
// 🚨 修正:Hostヘッダーを含んだ正しいHTTP/1.1リクエストを作成
req := "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n"
sendCmd := "AT+CIPSEND=" + strconv.Itoa(len(req))
res = sendATCommand(uart, sendCmd, 1*time.Second)
println("応答:\n", res)
// 実際のHTTPリクエストを送信
uart.Write([]byte(req))
// 🚨 修正:サーバーからの返信データを漏らさず溜める受信ループ
println("\n--- 受信データ (HTTP Response) ---")
var finalResponse []byte
readBuf := make([]byte, 128)
// データが流れ終わるまで、または3秒タイムアウトまでループ
readStart := time.Now()
for time.Since(readStart) < 3*time.Second {
if uart.Buffered() > 0 {
n, _ := uart.Read(readBuf)
finalResponse = append(finalResponse, readBuf[:n]...)
// データを受信したらタイムアウトタイマーを少し延長して追従する
readStart = time.Now()
}
time.Sleep(20 * time.Millisecond)
}
// 取得した生データを一括表示
print(string(finalResponse))
println("\n---------------------------------")
}
tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
--- TinyGo ESPAT Direct AT Command Control ---
[1/4] 生存確認中...
送信: AT
応答:
AT
OK
[2/4] Wi-Fiモード設定中...
送信: AT+CWMODE=1
応答:
AT+CWMODE=1
OK
[3/4] Wi-Fiアクセスポイントに接続中...
送信: AT+CWJAP="HUAWEI@nova@lite@3+","99991111"
応答:
AT+CWJAP="HUAWEI@nova@lite@3+","99991111"
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IP
OK
[4/4] TCP接続テスト (example.com)...
送信: AT+CIPSTART="TCP","example.com",80
応答:
AT+CIPSTART="TCP","example.com",80
CONNECT
OK
送信: AT+CIPSEND=56
応答:
AT+CIPSEND=56
OK
>
--- 受信データ (HTTP Response) ---
Recv 56 bytes
SEND OK
+IPD,927:HTTP/1.1 200 OK
Date: Sun, 01 Nov 2026 04:00:21 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: close
S
Age: 14269
cf-cache-status: HIT
CF-RAY: a537fdf6794fd3f5-KIX
alt-svc: h3=":443"; ma=86400
241
<!doctype html><html langh,initial-scale=1"><title>Example Domain</title><style>html{color-scheme:light dark;background:light-dark(#eee,#222)}body{font:1</head><body><p>This domain is for use in documentation examples without needing permission. This is not a service; avoid relyin
CLOSED
----------ssd1306 gpio4,gpio5でないと出ん,gpio0,gpio1はuart専用みたい!---------------------
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/ssd1306"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freesans"
)
func main() {
println("Starting SSD1306")
// I2C0 初期化
err := machine.I2C0.Configure(machine.I2CConfig{
SDA: machine.GP4,
SCL: machine.GP5,
Frequency: 100 * machine.KHz,
})
if err != nil {
println("I2C initialization failed:", err.Error())
return
}
println("I2C initialized")
// SSD1306 初期化
display := ssd1306.NewI2C(machine.I2C0)
display.Configure(ssd1306.Config{
Address: 0x3C,
Width: 128,
Height: 64,
})
println("SSD1306 initialized")
time.Sleep(time.Millisecond * 200)
// 画面クリア
display.ClearDisplay()
white := color.RGBA{
R: 255,
G: 255,
B: 255,
A: 255,
}
// 文字表示
tinyfont.WriteLine(
display,
&freesans.Regular12pt7b,
10,
25,
"Hello",
white,
)
tinyfont.WriteLine(
display,
&freesans.Regular12pt7b,
10,
50,
"TinyGo",
white,
)
// OLED更新
err = display.Display()
if err != nil {
println("Display error:", err.Error())
return
}
println("Display completed")
for {
time.Sleep(time.Second)
}
}
---------------------------------------------------------------------------------
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/dht"
)
func main() {
// DHT11 DATA → Pico GP0
pin := machine.GP0
sensor := dht.New(pin, dht.DHT11)
for {
// 温度と湿度を同時に取得
temp, hum, err := sensor.Measurements()
if err != nil {
fmt.Printf("DHT11 Error: %v\n", err)
} else {
fmt.Printf(
"Temperature: %d.%d C, Humidity: %d.%d %%\n",
temp/10,
temp%10,
hum/10,
hum%10,
)
} // DHT11は最低でも約1秒空ける
time.Sleep(2 * time.Second)
}
}
空スケッチをいれてuno r3にesp01をtx,rxをクロスしないで接続する
ATを入れる際に、baudrateが115200でないと接続できんのを確かめた!
ソフトシリアルを使うときは9600にする必要があるらしいが以下のサンプルコードは
115200でesp01と通信しているようだ。。。ゼロからよくわかる!Arduino電子工作 より
まずserverにおりてgo run main.goでaddress with portをcheck
package main
// TinyGo Pico W HTTP Client
// Build with -scheduler=tasks
import (
"context"
"errors"
"io"
"log/slog"
"machine"
"net/netip"
"time"
"github.com/soypat/cyw43439"
"github.com/soypat/cyw43439/examples/cywnet"
"github.com/soypat/cyw43439/examples/cywnet/credentials"
"github.com/soypat/lneto/http/httpraw"
"github.com/soypat/lneto/ipv4"
"github.com/soypat/lneto/tcp"
)
const (
connTimeout = 5 * time.Second
tcpbufsize = 2030
// HTTPサーバーのIPアドレスとポート
serverAddrStr = "192.168.0.6:8080"
ourHostname = "tinygo-http-client"
)
// DHCPで要求するIPアドレス
var requestedIP = [4]byte{192, 168, 0, 99}
func main() {
// USBシリアル接続待ち
time.Sleep(2 * time.Second)
logger := slog.New(
slog.NewTextHandler(
machine.Serial,
&slog.HandlerOptions{
Level: slog.LevelInfo,
},
),
)
println("--- Pico W HTTP Client Start ---")
// ========================================
// Wi-Fi 初期化
// ========================================
devcfg := cyw43439.DefaultWifiConfig()
devcfg.Logger = logger
cystack, err := cywnet.NewConfiguredPicoWithStack(
credentials.SSID(),
credentials.Password(),
devcfg,
cywnet.StackConfig{
Hostname: ourHostname,
MaxActiveTCPPorts: 1,
},
)
if err != nil {
panic("WiFi setup failed: " + err.Error())
}
// ========================================
// ネットワーク処理開始
// ========================================
go loopForeverStack(cystack)
// ========================================
// DHCP
// ========================================
dhcpResults, err := cystack.SetupWithDHCP(
cywnet.DHCPConfig{
RequestedAddr: netip.AddrFrom4(requestedIP),
},
)
if err != nil {
panic("DHCP failed: " + err.Error())
}
logger.Info(
"DHCP complete",
slog.String(
"addr",
ipv4.String(dhcpResults.AssignedAddr4),
),
)
// ========================================
// HTTPサーバーアドレス
// ========================================
serverAddr, err := netip.ParseAddrPort(serverAddrStr)
if err != nil {
panic("Server address error: " + err.Error())
}
// ========================================
// TCPスタック
// ========================================
stack := cystack.StackAsync()
rstack := stack.StackRetrying(
cywnet.DefaultStackBackoff,
)
// ========================================
// TCP接続設定
// ========================================
var conn tcp.Conn
err = conn.Configure(
tcp.ConnConfig{
RxBuf: make([]byte, tcpbufsize),
TxBuf: make([]byte, tcpbufsize),
TxPacketQueueSize: 3,
// lneto v0.4.0 では必須 ここが重要げ
RWBackoff: cywnet.DefaultStackBackoff,
},
)
if err != nil {
panic("conn configure: " + err.Error())
}
// ========================================
// HTTP GET リクエスト作成
// ========================================
var hdr httpraw.HeaderV1
hdr.SetMethod("GET")
hdr.SetRequestTarget(
"/update?t=23&h=45",
)
hdr.SetProtocol("HTTP/1.1")
hdr.Set(
"Host",
serverAddr.String(),
)
hdr.Set(
"Connection",
"close",
)
reqbytes, err := hdr.AppendRequest(nil)
if err != nil {
panic("HTTP request error: " + err.Error())
}
logger.Info(
"http:ready",
slog.String("serveraddr", serverAddrStr),
)
// ========================================
// TCP接続・HTTP送信
// ========================================
rxBuf := make([]byte, 4096)
for {
time.Sleep(2 * time.Second)
// ランダムなローカルポート
localPort := uint16(stack.Prand32()>>17) + 1024
logger.Info(
"TCP dialing",
slog.String("server", serverAddrStr),
)
// TCP接続
err = rstack.DoDialTCP(
context.Background(),
&conn,
localPort,
serverAddr,
connTimeout,
3,
)
if err != nil {
logger.Error(
"TCP dial failed",
slog.String("err", err.Error()),
)
closeConn(&conn)
continue
}
logger.Info("TCP connected")
// ====================================
// HTTP GET送信
// ====================================
logger.Info(
"HTTP GET sending",
slog.String(
"path",
"/update?t=23&h=45",
),
)
_, err = conn.Write(reqbytes)
if err != nil {
logger.Error(
"HTTP write failed",
slog.String("err", err.Error()),
)
closeConn(&conn)
continue
}
// 送信完了待ち
err = conn.Flush()
if err != nil {
logger.Error(
"HTTP flush failed",
slog.String("err", err.Error()),
)
closeConn(&conn)
continue
}
// ====================================
// HTTPレスポンス受信
// ====================================
println("--- HTTP Response ---")
_ = conn.SetReadDeadline(
time.Now().Add(5 * time.Second),
)
for {
n, readErr := conn.Read(rxBuf)
if n > 0 {
_, _ = machine.Serial.Write(
rxBuf[:n],
)
}
if readErr != nil {
if !errors.Is(readErr, io.EOF) {
logger.Info(
"HTTP read finished",
slog.String("err", readErr.Error()),
)
}
break
}
if n == 0 {
break
}
}
println("\n--- HTTP Complete ---")
closeConn(&conn)
// 1回送信して終了
return
}
}
// ============================================
// TCP接続終了処理
// ============================================
func closeConn(conn *tcp.Conn) {
_ = conn.Close()
for i := 0; i < 50; i++ {
if conn.State().IsClosed() {
break
}
time.Sleep(100 * time.Millisecond)
}
conn.Abort()
}
// ============================================
// ネットワーク処理ループ
// ============================================
func loopForeverStack(stack *cywnet.Stack) {
for {
send, recv, _ := stack.RecvAndSend()
if send == 0 && recv == 0 {
time.Sleep(5 * time.Millisecond)
}
}
}
fseiigojp@fseigojpPC:~$ source circup-env/bin/activate
(circup-env) fseiigojp@fseigojpPC:~$ circup adafruit_requests
Usage: circup [OPTIONS] COMMAND [ARGS]...
Try 'circup --help' for help.
Error: No such command 'adafruit_requests'.
(circup-env) fseiigojp@fseigojpPC:~$ circup install adafruit_requests
Found device raspberry_pi_pico2_w at /run/media/fseiigojp/CIRCUITPY, running CircuitPython 10.3.1.
Downloading 'py' bundle for adafruit/Adafruit_CircuitPython_Bundle (20261028).
py:
Extracting: [####################################] 100%
OK
Downloading '10mpy' bundle for adafruit/Adafruit_CircuitPython_Bundle (20261028).
10.x-mpy:
Extracting: [####################################] 100%
OK
Using latest bundle for adafruit/Adafruit_CircuitPython_Bundle (20261028).
Using latest bundle for adafruit/CircuitPython_Community_Bundle (20261008).
Searching for dependencies for: ['adafruit_requests']
Ready to install: ['adafruit_connection_manager', 'adafruit_requests']
Installed 'adafruit_connection_manager'.
Installed 'adafruit_requests'.
(circup-env) fseiigojp@fseigojpPC:~$
以後は同一LANでかつ2.5GHz帯であることが重要
ーーーーーーーーーーーーーーーーーーーーーーーーー
settings.toml (設定ファイル)
同じくルート(CIRCUITPY ドライブの直下)に配置してください。これがないとWi-Fiにーーーcode.pyでmonitorはthonnyをもちいるーーーーーーーーーーー
import os
import ssl
import wifi
import socketpool
import adafruit_requests
# ----------------------------------------------------
# 1. Wi-Fiへの接続
# ----------------------------------------------------
print("Wi-Fiに接続中...")
try:
# settings.toml からWi-Fi情報を読み込んで接続
wifi.radio.connect(
os.getenv("CIRCUITPY_WIFI_SSID"),
os.getenv("CIRCUITPY_WIFI_PASSWORD")
)
print(f"接続成功! IPアドレス: {wifi.radio.ipv4_address}")
except Exception as e:
print(f"Wi-Fi接続エラー: {e}")
raise
# ----------------------------------------------------
# 2. ネットワークセッションのセットアップ
# --------------httpsのみでなくhttpにもアクセスできる--------------------------------------
pool = socketpool.SocketPool(wifi.radio)
ssl_context = ssl.create_default_context()
requests = adafruit_requests.Session(pool, ssl_context)
# ----------------------------------------------------
# 3. HTTP GET リクエストの送信
# ----------------------------------------------------
# テスト用のURL(JSONデータを返すパブリックAPI)
URL = "http://192.168.0.10:3000"
print(f"GETリクエストを送信中: {URL}")
try:
response = requests.get(URL)
print(f"ステータスコード: {response.status_code}")
print("-" * 40)
# パターンA: レスポンスを「テキスト」としてそのまま表示する場合
print("【テキストとして表示】")
print(response.text)
print("-" * 40)
# パターンB: レスポンスを「JSON」として解析して特定のデータを抜く場合
print("【JSONとして解析して表示】")
data = response.json()
print(f"送信元IP (origin): {data.get('origin')}")
print(f"ユーザーエージェント (headers): {data.get('headers', {}).get('User-Agent')}")
# 使い終わったらクローズ
response.close()
except Exception as e:
print(f"リクエストエラー: {e}")
print("-" * 40)
print("処理が完了しました。")
//-------------------------------------------------------------------------------------------
// Tested Module : ERC1602-4, EASTRISING TECHNOLOGY CO,.LTD.
// Drive IC : ST7032
// INTERFACE : I2C
// VDD : 2.7V-5.5V
// Tested with MCU : Arduino Uno, Attiny85@1mhz(5.0V), Attiny85@8mhz(5.0V) and ESP8266(3.3V)
//-------------------------------------------------------------------------------------------
#include <LCD_ST7032.h> // library managerでzipでなくて成功した
LCD_ST7032 lcd;
void setup() {
lcd.begin();
lcd.setcontrast(24); //contrast value range is 0-63, try 25@5V or 50@3.3V as a starting value
}
void loop() {
static int counter = 0;
// Write a piece of text on the first line...
lcd.setCursor(0, 0); //LINE 1, ADDRESS 0
lcd.print("HelloYou");
// Write the counter on the second line...
lcd.setCursor(1, 0);
lcd.print(counter/10, DEC);
lcd.write('.');
lcd.print(counter%10, DEC);
lcd.write(' ');
delay(500);
counter++;
}
// smpの有無は関係なし
---------------------------------------------------------
#include <Wire.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme; // I2C接続
void setup() {
Serial.begin(115200);
while(!Serial);
// BME280のI2Cアドレスは一般的に 0x76 または 0x77
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
void loop() {
Serial.print("Temperature = ");
Serial.print(bme.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.readHumidity());
Serial.println(" %");
delay(1000);
}
---------------------------------------------------
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLEDの幅(ピクセル)
#define SCREEN_HEIGHT 64 // OLEDの高さ(ピクセル)※32の場合は32に変更
// SSD1306ディスプレイの宣言(リセットピンがない場合は -1)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
Serial.begin(115200);
// SSD1306のI2Cアドレスは一般的に 0x3C
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // 起動失敗時はここでストップ
}
display.clearDisplay(); // 画面バッファをクリア
display.setTextSize(1); // 文字サイズ(1〜)
display.setTextColor(SSD1306_WHITE); // 文字色(白)
display.setCursor(0, 0); // 左上にカーソルを移動
display.println("Hello, Pico!");
display.println("SSD1306 OLED Test");
display.display(); // 実際に画面に描画を反映
}
void loop() {
// ループ処理(今回は静止画面のまま)
}