ただのLチカがこれまた

投稿日:

 釣りは「へら鮒に始まりへら鮒に終わる」と言うそうだが、「ArduinoはLチカに始まりLチカに終わる」などと誰かが言っていそうで多分誰も言っていない(笑)。

 さておき、けっこう楽しいんだよな、Lチカ。

 で、なんっか、手持ちのものをいろいろとくっつけたくなるのだ。今日目に入ったのはSeeedstudio SIDEKICK BASIC KITに入っていた青いポテンショメータ。私が少年の頃は「バリオーム」「ボリューム」「可変抵抗」と言ったものだが、今はポテンショメータと言うそうな。

 ポテンショメータでLチカのスピードを調整してみよう。

 まず、ポテンショメータのスペックシートなどがなくてはっきりしないから、テスターを当てて抵抗を測る。0Ωから10.5kΩまで変化できることがわかった。

 このまま直列に+5Vを印加してアナログピンに入力してしまいそうだが、0Ωの時に過電流になってしまうから、10kΩの別の抵抗と直列に入れた方がいいだろう。そうするとポテンショメータを最小に回し切っても0.5mAくらいに抑えられる。

 計算はどうなるかというと、こんなようなことになる。

IMG_3161

 式に代入すれば、ポテンショメータを最大抵抗にしたとき2.44V、最小抵抗にしたとき0Vになることがわかる。

 プロトタイピングシールドのブレッドボードは小さくて全部の部品が載らないから、普段使っている普通のブレッドボードにつける。

IMG_3157

 動かすとこんな感じだ。

 スケッチはこんな感じ。

//
//  vr2speed.ino
//    ポテンショメータでLチカ制御
//    27.07.26(日)1300~
//    佐藤俊夫
//
const unsigned int
  STARTPIN  = 2,
  ENDPIN    = 8,
  INPUTPIN  = 9,
  VR        = 0,
  DELAYMIN  = 5,
  DELAYMAX  = 100;
const float
  V0 = 5.0,         //  +5V
  R1 = 10000.0,     //  アナログピンに入れるための電流制限抵抗10kΩ
  VRMIN = 0.0,      //  ポテンショメータの最小抵抗実測値 0Ω
  VRMAX = 10500.0;  //  ポテンショメータの最大抵抗実測値 10.5kΩ
//
void setup() {
  //  330Ωをカソードにそれぞれ入れてデジタル2~8番にLEDを繋いである。
  for(int i = STARTPIN; i <= ENDPIN; i++){
    pinMode(i, OUTPUT);
  }
  //  タクトスイッチは9番に繋いでアースし、内蔵プルアップ抵抗を使っている。
  pinMode(INPUTPIN, INPUT_PULLUP);
  //  ポテンショメータは10kΩ抵抗と直列に繋ぎ、間から出力を取っている。
  pinMode(VR, INPUT);
}

void loop() {
  static int i = STARTPIN, RLdirection = 1, delaytime = DELAYMIN;
  static unsigned long int prevtime = 0;
  if(prevtime + delaytime < millis()){
    digitalWrite(i, LOW);
    i += RLdirection;
    if(i > ENDPIN) i = STARTPIN;
    if(i < STARTPIN) i = ENDPIN;
    digitalWrite(i, HIGH);
    prevtime = millis();
  }
  if(digitalRead(INPUTPIN) == LOW){
    delay(500);
    RLdirection *= -1;
  }
  float v1 = (V0 * R1) / (R1 + VRMAX);
  float vr = analogRead(VR) * (V0 / 1024);
  delaytime = constrain(fmap(vr, v1, 0.0, DELAYMAX, DELAYMIN), DELAYMIN, DELAYMAX);
}

float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
  //  もともとの「map()」がlong int型でこの用途に合わないので、float型を定義
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}




出来る限り美しく

投稿日:

 同じLチカをやるのでも、単線タイプのジャンプワイヤをちゃんと使い、できる限りブレッドボード上を整然と配置してみた。これまではあまりそんなことは考えていなかったからだ。

 とりあえず持っているLEDを持っている330Ωの電流制御抵抗の個数の限り配置した。タクトスイッチをつけて、入力を受け付けるようにする。とりあえず、LEDの点滅が右から左へ流れ、タクトスイッチを押すたびに左右の向きが入れ替わる、というふうにしよう。

IMG_3153

 タクトスイッチの入力にプルダウン抵抗を取り付けるスペースがなくなってしまったので、内蔵プルアップ抵抗を使うことにし、負論理にする。

 動かすとこんな感じだ。

 スケッチはこんな感じ。

//
//  smartBreadboard.ino
//    出来るだけ美しくブレッドボードを作ってみた。
//    27.07.26(日)0800~
//    佐藤俊夫
//
const unsigned int
  STARTPIN  = 2,
  ENDPIN    = 8,
  INPUTPIN  = 9,
  DELAYTIME = 50;
//
void setup() {
  //  330Ωをカソードにそれぞれ入れてデジタル2~8番にLEDを繋いである。
  for(int i = STARTPIN; i <= ENDPIN; i++){
    pinMode(i, OUTPUT);
  }
  //  タクトスイッチは9番に繋いでアースし、内蔵プルアップ抵抗を使っている。
  pinMode(INPUTPIN, INPUT_PULLUP);
}

void loop() {
  static int i = STARTPIN, j = 1;
  static unsigned long int prevtime = 0;
  if(prevtime + DELAYTIME < millis()){
    digitalWrite(i, LOW);
    i += j;
    if(i > ENDPIN) i = STARTPIN;
    if(i < STARTPIN) i = ENDPIN;
    digitalWrite(i, HIGH);
    prevtime = millis();
  }
  if(digitalRead(INPUTPIN) == LOW){
    delay(500 );
    j *= -1;
  }
}

空の写真リベンジ

投稿日:

 先週試したAdafruit製の「小型TTLシリアルjpegカメラ」での間欠撮影先週はどうしたわけか同じ画像ばかり撮れてしまい、失敗である。

 (チナミに、このカメラのメーカーの「Adafruit」という会社、有名なマッシモ・バンジのTEDの中で紹介されていたことに気付いた。)

https://youtube.com/watch?v=UoBUXOOdLXY%3Ft%3D5m50s

 気を取り直して、スケッチを直す。撮影時のカメラのステータスを確認し、撮れていなければ何回でも撮り続ける。

「while(撮れてない)撮る;」

……というわけだ。まあ、万が一ハードウェアエラーなどがあるとループが回り続けるので良くないが、ループが回り続けようが結局のところはモノとしては電源を入れ直す他にどうしようもないので、こんなものだろう。

 それと、撮影が終わったらカメラをそのつどリセットすることにした。また、既に存在するファイル名は避けるようにした。こういう時、Arduinoには書式文字列付きの「sprintf」がないので、少し不便だなと思う。

 夜明けから日没までの一日の空の雲を撮りたいので、天気予報を見て雨が降らぬ確信を持ってから、昨夜寝る前にベランダにカメラをセットしておいた。朝早く起きるより楽だからだ。夜のうちに1000枚くらい写真が撮れてしまうが、SDカードには余裕があるので大丈夫である。

 昼間は用事があるのでカメラの面倒は見れないが、放置しておけば淡々と写真は撮れていく。

IMG_3143

 で、撮れた写真をWindows Movie Makerに流し込むと、微速撮影動画の一丁上がりだ。

 スケッチは次のとおりである。

//
//  camera2Web.ino
//    27.07.20(月) 0850~
//    佐藤俊夫
//    Adafruit製小型TTLシリアルJPEGカメラ+ETHERNET SHIELD 2で
//    間欠撮影をし、Webでダウンロードできるようにする。
//
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <Ethernet2.h>

#define CHIPSELECT 4

SoftwareSerial CAMCONNECTION(2, 3);
Adafruit_VC0706 CAM = Adafruit_VC0706(&CAMCONNECTION);
const unsigned long int INTERVAL = 30L * 1000L;
byte MAC[] = {  0x90, 0xA2, 0xDA, 0x0F, 0xF6, 0x74 };
IPAddress IP(192, 168, 1, 129);
EthernetServer SERVER(80);
EthernetClient CLIENT;

void setup() {
  pinMode(10, OUTPUT);
  if(!SD.begin(CHIPSELECT)) return;
  if(!CAM.begin()) return;
  CAM.setImageSize(VC0706_320x240);
  Ethernet.begin(MAC, IP);
  SERVER.begin();
  delay(1000);
}

void loop() {
  static unsigned long int prevtime = 0;
  char c;
  String rstr = "";
  //  INTERVALおきに写真を撮る
  if(millis() >= prevtime + INTERVAL){
    prevtime = millis();
    takePicture();
  }
  //  Webサーバ
  CLIENT = SERVER.available();
  if(CLIENT) {
    while(CLIENT.connected()) {
      if(CLIENT.available()) {
        c = CLIENT.read();
        rstr += c;
        if(rstr.endsWith("\r\n")){
          break;
        }
      }
    }
    if(rstr.indexOf("IMG") >= 0){
      String filename = "DCIM/";
      char cfilename[17];
      filename.concat(rstr.substring(rstr.indexOf("IMG"), rstr.indexOf("JPG") + 3));
      filename.toCharArray(cfilename, 17);
      CLIENT.println("HTTP/1.1 200 OK");
      CLIENT.println("Content-Type: image/jpg");
      CLIENT.println("Connection: close");
      CLIENT.println();
      File img = SD.open(cfilename);
      while(img.available()){
        CLIENT.write(img.read());
      }
      img.close();
    }else{
      sendform();
    }
    rstr = "";
    delay(1);
    // close the connection:
    CLIENT.stop();
  }
  delay(20);
}

void sendform(){
  //  フォームを送る。
  CLIENT.println("HTTP/1.1 200 OK");
  CLIENT.println("Content-Type: text/html");
  CLIENT.println("Connection: close");
  CLIENT.println();
  CLIENT.println("<!DOCTYPE HTML>");
  CLIENT.println("<html><head></head><body><center>");
  File dcim = SD.open("/DCIM");
  while(true) {
    File imgfile =  dcim.openNextFile();
    if(!imgfile){
      dcim.rewindDirectory();
      break;
    }
    CLIENT.write("<a href=\"");
    CLIENT.write(imgfile.name());
    CLIENT.write("\">");    
    CLIENT.write(imgfile.name());
    CLIENT.println("</a><br>");
    imgfile.close();    
  }
  dcim.close();
  CLIENT.println("</center></body></html>");
}

void takePicture(){
  static unsigned int pnum = 0;
  char filename[] = "DCIM/img0000.jpg";
  while(!CAM.takePicture());
  do{
    filename[8]  = '0' + pnum / 1000;
    filename[9]  = '0' + (pnum / 100) % 10;
    filename[10] = '0' + (pnum /  10) % 10;
    filename[11] = '0' + pnum % 10;
    pnum ++;
  }while(SD.exists(filename));
  if(pnum > 9999) pnum = 0;
  File imgFile = SD.open(filename, FILE_WRITE);
  uint16_t jpglen = CAM.frameLength();
  pinMode(8, OUTPUT);
  while (jpglen > 0) {
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen);
    buffer = CAM.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    jpglen -= bytesToRead;
  }
  while(!CAM.reset());
  imgFile.close();
}




熱帯夜

投稿日:

グラジオラス

投稿日:
()とせ()つグラジオラスの家を()ふ  佐藤俊夫 

#kigo #jhaiku #haiku #saezuriha  (季語は「グラジオラス」)