08/25/2019

DHT11 で計測の温度と湿度を TM1637 に表示する

Thd11tm1637 Dht11tm1637
TM1637は、7セグメント4桁表示器なので、「℃」や「%」の表示は、7セグメントの1文字では表示できない。
それゆえ、写真にあるように「℃」と「%」を簡易表示するようにした。
温度と湿度は、1秒ごとに切り替えて表示する。

《ピン接続について》
① DHT11 の左から2番目の信号ピン -> D2
② TM1637 の CLK -> D9
③ TM1637 の DIO -> D10 


《Sketch》
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include "DHT.h"
#define DHTPIN 2 // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.
#include <TM1637Display.h>
#define CLK 9   //can be any digital pin
#define DIO 10 //can be any digital pin
#define CHAR_DEG 0b01100011
#define CHAR_C 0b00111001

// Uncomment whatever type you're using!
#define DHTTYPE DHT11    // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors. This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);
TM1637Display display(CLK, DIO);
const uint8_t Letter_deg[] = { SEG_A | SEG_B | SEG_F | SEG_G };
const uint8_t Letter_C[] = { SEG_A | SEG_D | SEG_E | SEG_F };
const uint8_t Letter_o[] = { SEG_C | SEG_D | SEG_E | SEG_G };

void setup() {
Serial.begin(9600);
Serial.println(F("DHTxx test!"));
display.setBrightness(4); // 0x01 << dark -- bright >> 0x0f
display.clear();

dht.begin();
}

void loop() {
// Wait a few seconds between measurements.
delay(1000);

// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);

// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}

// Compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);

Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% Temperature: "));
Serial.print(t);
Serial.print(F("°C "));
Serial.print(f);
Serial.print(F("°F Heat index: "));
Serial.print(hic);
Serial.print(F("°C "));
Serial.print(hif);
Serial.println(F("°F"));

display.clear();
display.showNumberDec(t,false, 2, 0); // distance to front obstacle
display.setSegments(Letter_deg,1,2);
display.setSegments(Letter_C,1,3);
delay(1100);

display.clear();
display.showNumberDec(h,false, 2, 0); // distance to front obstacle
display.setSegments(Letter_deg,1,2);
display.setSegments(Letter_o,1,3);
delay(100);
}


《参考にした資料》
https://github.com/adafruit/DHT-sensor-library/blob/master/examples/DHTtester/DHTtester.ino

08/12/2019

Added comments to my Tank Robot sketches

Tank Robot の動き方をいろいろ調整して、ほぼ満足のゆく状況になってきた。Sketch については、前回のものに対して少し加筆修正も行ったが・・・、Sketch内の各ステートメントで、変数の意味は何で、また何の処理をしているのか、後で見直した際にも分かるように、コメントを追記した。
Img_20190808_115947

《 Sketch 》

const int PIN_SONAR_ECHO = 5; // define pin for sensor echo
const int PIN_SONAR_TRIGGER = 6; // define pin for sensor trig
#include <Servo.h>
#include <TM1637Display.h>
#define CLK 7 //can be any digital pin
#define DIO 8 //can be any digital pin
int Fdistance = 0; // Distance to the obstacle in the direction of the sensor
float Dlh; // Distance to left obstacle
float Drh; // Distance to right obstacle
float Dfr; // Distance to front obstacle
int Ls = 35 ; // short range threshold changed from 30
int Ll = 55 ; // long range threshold = 55
int angle;
int pinSRB = 9; // servo motor output pin (PWM)
int random_No4;
float multiplier = 1.35; // add variable and changed number from 1.3
int delaytime = 350; // chaged from 400
// next pins(10~13) are depended on L298P motorshield
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function from 10
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function
int FullSpeed = 255; // max 255
int HalfSpeed = 240; // when the number is less than 180 will be stopp
Servo myServo; // set myservo

TM1637Display display(CLK, DIO);
// Data setting for 7-segment display
const uint8_t Letter_F[] = { SEG_A | SEG_E | SEG_F | SEG_G }; // F
const uint8_t Letter_b[] = { SEG_C | SEG_D | SEG_E | SEG_F | SEG_G }; // b
const uint8_t Letter_H[] = { SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // H
const uint8_t Letter_r[] = { SEG_E | SEG_G }; // r
const uint8_t Letter_L[] = { SEG_D | SEG_E | SEG_F }; // L
const uint8_t Letter_A[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // A
const uint8_t Letter_c[] = { SEG_D | SEG_E | SEG_G }; // c
const uint8_t Letter_t[] = { SEG_D | SEG_E | SEG_F | SEG_G }; // t
const uint8_t Letter_LT[] = { SEG_A | SEG_F | SEG_G }; // <
const uint8_t Letter_GT[] = { SEG_A | SEG_B | SEG_G }; // >

void setup()
{
  Serial.begin(9600);
  pinMode(PIN_SONAR_TRIGGER,OUTPUT);
  pinMode(PIN_SONAR_ECHO,INPUT);
  display.setBrightness(0x0f); // 0x01 << dark -- bright >> 0x0f
  display.clear();
// Define motor output pin
  pinMode(pinLB,OUTPUT); // pin 12 direction control function
  pinMode(pinLF,OUTPUT); // pin 10 (PWM)
  pinMode(pinRB,OUTPUT); // pin 13 direction control function
  pinMode(pinRF,OUTPUT); // pin 11 (PWM)
  myServo.attach(pinSRB); // Define servo motor output pin(PWM)
}

void Advance() // move to forward
{
  display.setSegments(Letter_F,1,0); // display "go to foward"
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void Back() // move backward
{
  display.clear();
  display.setSegments(Letter_b,1,1); // display "go to backward"
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  delay(50);
  digitalWrite(pinLB,HIGH); // motor moves to left rear
  digitalWrite(pinRB,HIGH); // motor moves to right rear
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void MidSpeed() // move to forward
{
  display.setSegments(Letter_F,1,0); // display "go to foward"
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,HalfSpeed);
  analogWrite(pinRF,HalfSpeed);
}

void Stopp() // all wheel stop
{
  display.setSegments(Letter_H,1,0); // display "Stop"
  display.setSegments(Letter_A,1,1);
  display.setSegments(Letter_L,1,2);
  display.setSegments(Letter_t,1,3);
  digitalWrite(pinLB,HIGH); // left wheel stop
  digitalWrite(pinRB,HIGH); // right wheel stop
  analogWrite(pinLF,0);
  analogWrite(pinRF,0);
}

void BackRight() // turn right
{
  display.setSegments(Letter_r,1,0); // display "back right"
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB,HIGH);
  digitalWrite(pinRB, LOW); // wheel on the right moves backward
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void BackLeft() // turn left
{
  display.setSegments(Letter_L,1,0); // display "back left"
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB, LOW); // wheel on the left moves backward
  digitalWrite(pinRB,HIGH);
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void loop()
{
  labelF:
  long random_No1 = random( 20, 120); // Generate random numbers
// --- Forward obstacle detection and moving ---
// angle = 90;
  myServo.write(90); // use fixed number(90deg)
  delay(10); // changed delay time from 50

label1:  // add a statement
  ask_pin_F(); // Fdistance

  if(Fdistance <= Ls)
  {
    Stopp(); // stop for a while
    goto label2;
  }

  if((Fdistance > Ls ) & (Fdistance <= Ll ))
  {
    MidSpeed(); // at a slightly reduced speed
    goto label1;  // changed statement from labelF
  }

  if(Fdistance > Ll )
  {
    Advance();   // at full speed
    goto label1;  // changed statement from labelF
  }

label2:
// angle = 90; // Check the distance ahead again
  myServo.write(90); // use fixed number(angle --> 90)
  delay(10); // changed delay time from 50
  ask_pin_F();

  if(Fdistance < Ls )
  {
    Back(); // go back a little
    delay(random_No1); // backward progress time
    Stopp();
  }
// Measure left and right space
  angle = 3; // check for obstacles in the right direction
  myServo.write(angle);
  delay(1000); // time to reserve for servo motor
  ask_pin_F();
  Drh=Fdistance;

  angle = 177; // check for obstacles in the left direction
  myServo.write(angle);
  delay(1000); // time to reserve for servo motor
  ask_pin_F();
  Dlh=Fdistance;

  angle = 90; // check for obstacles ahead
  myServo.write(angle);
  delay(1000); // time to reserve for servo motor
  ask_pin_F(); // check forward distance
  Dfr=Fdistance;

label3:
  if(Dlh > Drh)
  {
    display.setSegments(Letter_GT,1,0); // display ">"
    delay(350); //changed delay time from 300
// Calculate the time to change the moving direction of the tank
// "ie. delay(random_No4)" from the distance to the obstacles
// in the front and rear direction and the side direction

    float rn1 = Dlh / Dfr ;

    if( rn1 >= multiplier ) rn1 = multiplier ; // changed sketch
    random_No4 = delaytime * rn1 ;
    BackRight();
    delay(random_No4); // backward progress time
    Stopp();
    delay(400); // display time for display unit
    goto labelF;

  }
else if( Dlh <= Drh )
{
  display.setSegments(Letter_LT,1,0); // display "<"
  delay(350); //changed delay time from 300

  float rn2 = Drh / Dfr ;

  if( rn2 >= multiplier ) rn2 = multiplier ; // changed sketch
  random_No4 = delaytime * rn2 ;
  BackLeft();
  delay(random_No4); // backward progress time
  Stopp();
  delay(400); // display time for display unit
  goto labelF;

  }
}

void ask_pin_F() // Measure the distance at the specified angle
{
  digitalWrite(PIN_SONAR_TRIGGER,LOW); // Set the trigger pin to low for 2micro_S
  delayMicroseconds(2);
  digitalWrite(PIN_SONAR_TRIGGER,HIGH); // Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(PIN_SONAR_TRIGGER,LOW); // Send pin low again
  float distance = pulseIn(PIN_SONAR_ECHO,HIGH); // Read in times pulse
  Fdistance = distance/58; // Calculate distance from time of pulse
  delay(60);
  if(( 89 < angle) & (angle < 91))    display.setSegments(Letter_F,1,0);
  if(( 0 < angle) & (angle < 35))      display.setSegments(Letter_r,1,0);
  if(( 145 < angle) & (angle < 180)) display.setSegments(Letter_L,1,0);
  display.showNumberDec(Fdistance,true, 3, 1); // distance to front obstacle
  delay(200); // changed display time from 300
}

08/11/2019

GPS Clock and display the time when posted to the post box

Img_20190810_153857Gps-watch-with-twelite
ポストボックスの蓋が開けられた際に、Twe-Liteを使って離れた場所にある書斎に信号を送り、投函されたという信号をLED点滅で表示する装置を以前に作った。
LEDの点滅ではわからない情報(例えば、何回投函された?何時投函された?)を表示させたいと思い、それぞれの目的に応じたものをNANOを用いて製作した。しかしNANOで作った前述の装置を見ると、使っているPINには重複が無いので、下記の①~⑤の内容を、1つのNANOで処理できると考え、これまで2個のNANOを使って表示していたものを纏めてみた。(写真は、壁のボードに各部品類を両面テープで貼り付けて設置している。)

①GPSによる時間捕捉
②4桁7セグメントを用いた時刻表示
③TWE-Liteからの投函信号
④8x8ドットマトリックスを用いた現在の投函数
⑤20x4LCDを用いた投函回数とその時刻表示(この表示器を用いれば、もう少し詳細なGPS時計としても表示出来る)

《使用した部品とポート間接続》
Arduino NANO --- 接続先
 Pin No.  
   A4  ---  SDA (20x4 LCD I2C 接続)
   A5  ---  SCL (20x4 LCD I2C 接続)
   D2  ---  TWE-Lite 受信後のフォトカプラより
   D3  --- RX (GPS)
   D4  --- TX (GPS)
   D6  ---  CLK (4桁7セグメント)
   D7  ---  DIO (4桁7セグメント)
   D10  ---  CS (8x8 ドットマトリックスディスプレイ)
   D11  ---  DIN (8x8 ドットマトリックスディスプレイ)
   D12  ---  NANO内部結線
   D13  ---  CLK (8x8 ドットマトリックスディスプレイ)

GPS: Cikuso  NEO-6M GPS module  GY-GPS6MV2

4桁7セグメントDisplay:
  KKHMF モジュールは12ピンの時計点付きの4位共通アノードデジタルチューブ(0.36インチ)の表示モジュール,
  ドライブチップはTM1637


TWI-Lite からの信号用フォトカプラ:

8x8ドットマトリックス:SODIAL(R) MAX7219

20x4 LCDディスプレイ:Aideepen  I2C HD44780コントローラ 
  Arduino対応(2004 LCD 5V blue)

《注記1》
これを記載した翌朝、新聞の投函があったので、表示装置を見ると・・・投函された際に表示する表記が想定していたのと違う!
表示の問題点が分かったので、2019/08/21 sketch(下記)を加筆修正した。また、Frizingを使って回路を記載した。しかし、LEDを1秒毎に点灯するためのデバイス(M34-1L)がないため、外観が同じものを流用して記述しているのでご容赦ください。

ダウンロード - gps20watch20with20twelite20sketch2020190821.fzz

注記2
Sketch の loop 内に if 文の範囲ミスが見つかったので2か所修正した。2019/08/28


《Sketch》
// GPS Clock and display the time when posted to the post box My Spice Cabinet
#include <Wire.h>
#include <TimeLib.h>     // include Arduino time library
#include <SoftwareSerial.h>  // include software serial library
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
const int numberOfHorizontalDisplays = 1;
const int numberOfVerticalDisplays = 1;
const int pinCS = 10; // Cs - SS (Pin 10)
// Din - Mosi (Pin 11)
// Clk - Sck (Pin 13)
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

#include <TinyGPS++.h> // include TinyGPS++ library
TinyGPSPlus gps;
static const int TXPin = 4, RXPin = 3;   // TX -> D4, RX -> D3
SoftwareSerial Serial_GPS(TXPin, RXPin);
static const uint32_t GPSBaud = 9600;

#include <LiquidCrystal_I2C.h>
#define I2C_ADDR  0x27
LiquidCrystal_I2C lcd(I2C_ADDR, 20, 4);   // I2C: 0x27 20x4 LCD
// LCD(20x4) --- Arduino NANO (I2C connection)
// GND --- GND
// VCC --- 5V
// SDA --- A4
// SCL --- A5

#include "SevenSegmentTM1637.h"
#include "SevenSegmentExtended.h"
const byte PIN_CLK = 6;    // define CLK pin (any digital pin)
const byte PIN_DIO = 7;    // define DIO pin (any digital pin)
SevenSegmentExtended display(PIN_CLK, PIN_DIO);
int Satellites = 12;
int hours;
int minutes;
const int UTC_offset = 9;   // Tokyo Japan Time
#define time_offset 3600   // define a clock offset of 3600 seconds (@hour)

// variable definitions
char Time[] = "Time: 00:00:00";
char Date[] = "Date: 00_   _2000";
char visit[]  = "            ";  // changed 20190821
byte last_second, Second, Minute, Hour, Day, Month;
int Year;

char time_value[20];
#define PUSH_SHORT 100
int count = 2;   // counter from outside TWE-Lite
int icount = 0;   // number of switched on
int jcount = 0;   // column location on the display
int row = 0;
char c;
String s;
String visitor;
int count_low = 0;

void setup(void)
{
Serial.begin(9600);                 // added 20190821
Serial_GPS.begin(GPSBaud);   // initialize software serial
display.begin();                      // initializes the display
display.setBacklight(30);         // set the brightness to 30%
matrix.setIntensity( 1 );         // Adjust the 8x8 brightness (dark)0 << 15(bright)
matrix.setPosition( 0, 3, 0);
matrix.setRotation( 0, 3) ;      // rotation position
pinMode(count, INPUT_PULLUP);

c = char(icount + 48);
Serial.print("c = ");
Serial.println(c);
matrix.drawChar( 2, 1, c, HIGH, LOW, 1);
matrix.write();    // Send bitmap to display
delay( 50);

pinMode(Satellites, INPUT_PULLUP);
delay(100);

// set up the 20x4 LCD's number of columns and rows
lcd.begin(20, 4);
lcd.init();
lcd.backlight();
lcd.setCursor(2, 0);    // move LCD cursor to column 1, row 0 [upper left position (0, 0)]
lcd.print("GPS clock (UTC_ )");
lcd.setCursor(17, 0);
lcd.print(UTC_offset);

Wire.begin();
pinMode(count, INPUT_PULLUP); // switch on signal from TWE-Lite
String s;
}

void loop()
{
  matrix.fillScreen(LOW);
  while (Serial_GPS.available() > 0)
  {
    if (gps.encode(Serial_GPS.read()))
    {
// get time from GPS module
    if (gps.time.isValid())
    {
      Minute = gps.time.minute();
      Second = gps.time.second();
      Hour = gps.time.hour();
    }

// get date drom GPS module
    if (gps.date.isValid())
    {
      Day = gps.date.day();
      Month = gps.date.month();
      Year = gps.date.year();
    }

    if(last_second != gps.time.second()) // if the time has changed
    {
      last_second = gps.time.second();
// set current UTC time
      setTime(Hour, Minute, Second, Day, Month, Year);
// add the offset to get local time
      adjustTime(UTC_offset*time_offset);

// update time array
      Time[12] = second() / 10 + '0';
      Time[13] = second() % 10 + '0';
      Time[9] = minute() / 10 + '0';
      Time[10] = minute() % 10 + '0';
      Time[8] = char(58) ;
      Time[6] = hour() / 10 + '0';
      Time[7] = hour() % 10 + '0';

      hours = hour();
      minutes = minute();
// update date array
      Date[15] = (year() / 10) % 10 + '0';
      Date[16] = year() % 10 + '0';
      Date[8] = char(47) ;
      Date[9] = month() / 10 + '0';
      Date[10] = month() % 10 + '0';
      Date[11] = " ";
      Date[6] = day() / 10 + '0';
      Date[7] = day() % 10 + '0';

      if(jcount == 0)
      {
// print time & date to 20x4 LCD display
        print_wday(weekday());   // print day of the week
        print_wmonth(month());

        lcd.setCursor(0, 2);   // move cursor to column 0 row 2
        lcd.print(Time); // print time (HH:MM:SS)

        lcd.setCursor(0, 3);   // move cursor to column 0 row 3
        lcd.print(Date); // print date (DD-MM-YYYY)
        print_wmonth(month());
      }

      display.printTime(hours, minutes, true);   // overwrite to LCD display
    }
//  }  // deleted 20190827

// http://techblog.wp.xdomain.jp/2018/10/27/arduino_tactile_switch/
  if(digitalRead(count) == LOW){   // when switch on
  if(count_low <= PUSH_SHORT) count_low ++;
  }else{   // switch off state
    count_low = 0;
  }
  if(count_low == PUSH_SHORT){
    Serial.println("Pushed Button!");
    icount = icount + 1 ;
    if(icount == 1 )  lcd.clear();
    displayInfo();   // display the number of visitor and the time
    jcount = jcount + 1 ;
  }
 }  // added 20190827
 }
}

// function for displaying day of the week
void print_wday(byte wday)
{
  lcd.setCursor(5, 1);   // move cursor to column 5, row 1
  switch(wday)
  {
    case 1: lcd.print(" Sunday "); break;
    case 2: lcd.print(" Monday "); break;
    case 3: lcd.print(" Tuesday "); break;
    case 4: lcd.print("Wednesday"); break;
    case 5: lcd.print("Thursday "); break;
    case 6: lcd.print(" Friday "); break;
    default: lcd.print("Saturday ");
  }
}

// function for displaying month of year
void print_wmonth(byte wmonth)
{
  lcd.setCursor( 9, 3);   // move cursor to column 9, row 3
  switch(wmonth)
  {
    case 1: lcd.print("Jan"); break;
    case 2: lcd.print("Feb"); break;
    case 3: lcd.print("Mar"); break;
    case 4: lcd.print("Apr"); break;
    case 5: lcd.print("May"); break;
    case 6: lcd.print("Jun"); break;
    case 7: lcd.print("Jul"); break;
    case 8: lcd.print("Aug"); break;
    case 9: lcd.print("Sep"); break;
    case 10: lcd.print("Oct"); break;
    case 11: lcd.print("Nov"); break;
    default: lcd.print("Dec");
  }
}

void displayInfo()
{     // write information to 20x4 LCD Display and 8x8 matrix Display
  c = char(icount + 48);
  visit[0] = hour() / 10 + '0';
  visit[1] = hour() % 10 + '0';
  visit[2] = char(58) ;  // changed 20190821
  visit[3] = minute() / 10 + '0';
  visit[4] = minute() % 10 + '0';
  visit[5] = char(32);  // changed 20190821

  visit[6] = month() / 10 + '0';
  visit[7] = month() % 10 + '0';
  visit[8] = char(47) ;  // changed 20190821
  visit[9] = day() / 10 + '0';
  visit[10]= day() % 10 + '0';

  if( row == 4 ) row = 0;
  lcd.setCursor(0, row);  // changed 20190821
  lcd.print("Posted");      // changed 20190821
  lcd.setCursor(7, row);  // changed 20190821
  lcd.print( c );
  lcd.setCursor(9, row);  // changed 20190821
  lcd.print(visit);
  Serial.print("Posted ");  // changed 20190821
  Serial.print(visit);         // changed 20190821

  matrix.drawChar( 2, 1, c, HIGH, LOW, 1);
  matrix.write();   // Send bitmap to display
  delay(100);
  row = row + 1;
}

08/07/2019

乱数発生関数で Tank Robot の動きに変化を付ける

Img_20190808_115947 Img_20190808_120054

何時も決められた同じような動きしかしないので、乱数発生関数を利用して、Sketchの数か所を書き直し、Tank Robotの動きに変化を付けてみた。
加えて、Tank Robotが斜め前方に進めるように、左右方向と前方、それぞれの干渉物までの距離を利用して、後方回転で方向変換する時間を調整するようにした。
乱数発生機能を使った事によって、時々意外な動きが加えられたので、見ていて、その動きに飽きなくなった。
電源のパワーが小さいので、これまでと同様に、超音波センサーで検出できない低い障害物などに捕まって、停まってしまう状況はあまり変わらない。
注記1)Sketchの中で、上記以外の新たな改善や変更も行った。
  モーターを低速で動かそうとして「HalfSpeed」という項目を作ったが、値が低いとモーターのパワーも落ちてしまうので、どれくらいの値にするのが良いか悩ましいところだ。ここでは、230としてみた。動画をアップロードしたいところだが・・・
注記2)Tank Robot が計測している示される方向と障害物迄の距離が合っていない。調べると、Sketch上で変数の型を無茶苦茶にして使っていた。いろいろな所から持ってきたり変更したりする間に、確認せず使っていた。これを見直さないとめちゃくちゃな処理になる。事実そうなっている。加えて、サーボモータを任意の角度で正しく止めるには、delayの時間を1000msは必要になる。しかし直進状態で前方との距離を計測する際には、サーボモーターは前方を向いているので、delay時間は必要無いだろう。入れることによって設定した距離で止まらず、障害物に激突してしまう。
ask_pin_F()の中に入れていた「myServo.write(angle)」を外に出して、直進状態と停まって左右を確認する場合のdelay時間を分けられるようにした。
その他、いろいろ変更したので・・・ 08/07 version は削除し、08/08 versionに置き換えた。未だ、問題点などあるかもしれないが・・・

《Sketch 2019/08/08 version》

const int PIN_SONAR_ECHO = 5; // define pin for sensor echo
const int PIN_SONAR_TRIGGER = 6; // define pin for sensor trig
#include <Servo.h>
#include <TM1637Display.h>
#define CLK 7 //can be any digital pin
#define DIO 8 //can be any digital pin
int Fdistance = 0;
float Dlh;
float Drh;
float Dfr; 
int Ls=30 ; // short range threshold 
int Ll=55 ; // long range threshold 
int angle;
int pinSRB= 9; // servo motor output pin (PWM)
int random_No4;
// next pins(10~13) are depended on L298P motorshield
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function from 10
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function
int FullSpeed = 255; // max 255
int HalfSpeed = 240; // when the number is less than 180 will be stopp
Servo myServo; // set myservo

TM1637Display display(CLK, DIO);
const uint8_t Letter_F[] = { SEG_A | SEG_E | SEG_F | SEG_G }; // F
const uint8_t Letter_b[] = { SEG_C | SEG_D | SEG_E | SEG_F | SEG_G }; // b
const uint8_t Letter_H[] = { SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // H
const uint8_t Letter_r[] = { SEG_E | SEG_G }; // r
const uint8_t Letter_L[] = { SEG_D | SEG_E | SEG_F }; // L
const uint8_t Letter_A[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // A
const uint8_t Letter_c[] = { SEG_D | SEG_E | SEG_G }; // c
const uint8_t Letter_t[] = { SEG_D | SEG_E | SEG_F | SEG_G }; // t
const uint8_t Letter_LT[] = { SEG_A | SEG_F | SEG_G }; // <
const uint8_t Letter_GT[] = { SEG_A | SEG_B | SEG_G }; // >

void setup()
{
  Serial.begin(9600);
  pinMode(PIN_SONAR_TRIGGER,OUTPUT);
  pinMode(PIN_SONAR_ECHO,INPUT);
  display.setBrightness(0x0f); // 0x01 << dark bright >> 0x0f
  display.clear();
// Define motor output pin
  pinMode(pinLB,OUTPUT); // pin 12 direction control function
  pinMode(pinLF,OUTPUT); // pin 10 (PWM)
  pinMode(pinRB,OUTPUT); // pin 13 direction control function
  pinMode(pinRF,OUTPUT); // pin 11 (PWM)
  myServo.attach(pinSRB); // Define servo motor output pin(PWM)
}

void Advance() // move to forward
{
  display.setSegments(Letter_F,1,0);
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void Back() // move backward
{
  display.clear();
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  delay(50);
  digitalWrite(pinLB,HIGH); // motor moves to left rear
  digitalWrite(pinRB,HIGH); // motor moves to right rear
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void MidSpeed() // move to forward
{
  display.setSegments(Letter_F,1,0);
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,HalfSpeed);
  analogWrite(pinRF,HalfSpeed);
}

void Stopp() // all wheel stop
{
  display.setSegments(Letter_H,1,0);
  display.setSegments(Letter_A,1,1);
  display.setSegments(Letter_L,1,2);
  display.setSegments(Letter_t,1,3);
  digitalWrite(pinLB,HIGH); // left wheel stop
  digitalWrite(pinRB,HIGH); // right wheel stop
  analogWrite(pinLF,0);
  analogWrite(pinRF,0);
}

void BackRight() // turn right
{
  display.setSegments(Letter_r,1,0);
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB,HIGH);
  digitalWrite(pinRB, LOW); // wheel on the right moves backward
  analogWrite(pinLF,FullSpeed); // from FullSpeed
  analogWrite(pinRF,FullSpeed); // from FullSpeed
}

void BackLeft() // turn left
{
  display.setSegments(Letter_L,1,0);
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB, LOW); // wheel on the left moves backward
  digitalWrite(pinRB,HIGH);
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void loop()
{
labelF:
  long random_No1 = random( 20, 120);
// --- Forward obstacle detection and moving ---
// angle = 90;
  myServo.write(90);
  delay(50);
  ask_pin_F(); // Fdistance

  if(Fdistance <= Ls)
  {
    Stopp(); // stop for a while
    goto label2;
  }
  if((Fdistance > Ls  ) & (Fdistance <= Ll ))
  {
    MidSpeed();
    goto labelF;
  }
  if(Fdistance > Ll )
  {
    Advance();
    goto labelF;
  }

label2:
// angle = 90; // Check the distance ahead again
  myServo.write(90);
  delay(50);
  ask_pin_F();
  if(Fdistance < Ls )
  {
    Back(); // go back a little
    delay(random_No1);
    Stopp();
  }
// Measure left and right space
  angle = 3;
  myServo.write(angle);
  delay(1000);
  ask_pin_F();
  Drh=Fdistance;

  angle = 177;
  myServo.write(angle);
  delay(1000);
  ask_pin_F();
  Dlh=Fdistance;

  angle =90; //added
  myServo.write(angle);
  delay(1000);
  ask_pin_F(); // check forward
  Dfr=Fdistance;

label3:
  if(Dlh > Drh)
  {
    display.setSegments(Letter_GT,1,0);
    delay(300);

      float rn1 = Dlh / Dfr ;

      if( rn1 >= 1.3 ) rn1 = 1.3 ;
      random_No4 = 400 * rn1 ;
      BackRight();
      delay(random_No4);
      Stopp();
      delay(400);
      goto labelF;

  }
  else if( Dlh <= Drh )
  {
    display.setSegments(Letter_LT,1,0);
    delay(300);

      float rn2 = Drh / Dfr ;

      if( rn2 >= 1.3 ) rn2 = 1.3 ;
      random_No4 = 400 * rn2 ;
      BackLeft();
      delay(random_No4);
      Stopp();
      delay(400);
      goto labelF;

  }
}

void ask_pin_F() // Measure the distance at the specified angle
{
  digitalWrite(PIN_SONAR_TRIGGER,LOW);// Set the trigger pin to low for 2uS
  delayMicroseconds(2);
  digitalWrite(PIN_SONAR_TRIGGER,HIGH);// Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(PIN_SONAR_TRIGGER,LOW);// Send pin low again
  float distance = pulseIn(PIN_SONAR_ECHO,HIGH);// Read in times pulse
  Fdistance = distance/58;// Calculate distance from time of pulse
  delay(60);
  if(( 89 < angle) & (angle < 91)) display.setSegments(Letter_F,1,0);
  if(( 0 < angle) & (angle < 35)) display.setSegments(Letter_r,1,0);
  if(( 145 < angle) & (angle < 180)) display.setSegments(Letter_L,1,0);
  display.showNumberDec(Fdistance,true, 3, 1);
  delay(300);
}

08/06/2019

Arduino Tank Robot Sketch修正

Tank Robotを動かして、その挙動を見ていると、いろいろ気になるところが出てくる。間違えてプログラムを書いていたところもある。
こうすれば、もっと無駄な動きが少なくなるだろうと思って複雑にしてゆくと、逆に思わぬところでフリーズしてしまう。
それでプログラムは、なるべくシンプルにして・・・ 超音波距離測定も、ライブラリーを使っていたが、計測距離が大きく表示されるので、それらの課題も入れて、少し直してみた。
動かしている際の問題点として、下記のようなものがある。
 ①センサーの高さが高いので、高さの低い障害物との距離を計測出来ない。
 ②平面を持った障害物に対して、棒や細い柱のようなものは上手く補足できない。
 ③クローラーの高さに近い高さの窪みに嵌り込んで、動けなくなる。
 ④段差がある場所や、ちょっと太めの電線ケーブル等を跨いでしまうと、動かなくなる場合がある。
 ⑤摩擦係数の低い床では、クローラーが滑ってスケートでもしているような動きになる。
 ⑥超音波センサーの高さを床面から50mmぐらいの高さで設置できれば、上記の課題の幾つかは解消できるかもしれない。

《Sketch 2019/8/6 version》

const int PIN_SONAR_ECHO = 5; // define pin for sensor echo
const int PIN_SONAR_TRIGGER = 6; // define pin for sensor trig
#include <Servo.h>
#include <TM1637Display.h>
#define CLK 7 //can be any digital pin
#define DIO 8 //can be any digital pin
double Fdistance = 0;
double Dlh;
double Drh;
double Dfr;
double Ls = 30; // short range threshold
double Ll = 55; // long range threshold
int angle;
int pinSRB= 9; // servo motor output pin (PWM)

// next pins(10~13) are depended on L298P motorshield
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function from 10
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function

int FullSpeed = 255; // max 255
int HalfSpeed = 200; // when the number is less than 180 will be stopp
Servo myServo; // set myservo

TM1637Display display(CLK, DIO);
const uint8_t Letter_F[] = { SEG_A | SEG_E | SEG_F | SEG_G }; // F
const uint8_t Letter_b[] = { SEG_C | SEG_D | SEG_E | SEG_F | SEG_G }; // b
const uint8_t Letter_H[] = { SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // H
const uint8_t Letter_r[] = { SEG_E | SEG_G }; // r
const uint8_t Letter_L[] = { SEG_D | SEG_E | SEG_F }; // L
const uint8_t Letter_A[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // A
const uint8_t Letter_c[] = { SEG_D | SEG_E | SEG_G }; // c
const uint8_t Letter_t[] = { SEG_D | SEG_E | SEG_F | SEG_G }; // t
const uint8_t Letter_LT[] = { SEG_A | SEG_F | SEG_G }; // <
const uint8_t Letter_GT[] = { SEG_A | SEG_B | SEG_G }; // >

void setup()
{
  Serial.begin(9600);
  pinMode(PIN_SONAR_TRIGGER,OUTPUT);
  pinMode(PIN_SONAR_ECHO,INPUT);
  display.setBrightness(0x0f); // 0x01 << dark bright >> 0x0f
  display.clear();
// Define motor output pin
  pinMode(pinLB,OUTPUT); // pin 12 direction control function
  pinMode(pinLF,OUTPUT); // pin 10 (PWM)
  pinMode(pinRB,OUTPUT); // pin 13 direction control function
  pinMode(pinRF,OUTPUT); // pin 11 (PWM)
  myServo.attach(pinSRB); // Define servo motor output pin(PWM)
}

void Advance() // move to forward
{
  display.setSegments(Letter_F,1,0);
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void Back() // move backward
{
  display.clear();
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  delay(50);
  digitalWrite(pinLB,HIGH); // motor moves to left rear
  digitalWrite(pinRB,HIGH); // motor moves to right rear
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void MidSpeed() // move to forward
{
  display.setSegments(Letter_F,1,0);
  digitalWrite(pinLB,LOW); // left wheel moves forward
  digitalWrite(pinRB,LOW); // right wheel moves forward
  analogWrite(pinLF,HalfSpeed);
  analogWrite(pinRF,HalfSpeed);
}

void Stopp() // all wheel stop
{
  display.setSegments(Letter_H,1,0);
  display.setSegments(Letter_A,1,1);
  display.setSegments(Letter_L,1,2);
  display.setSegments(Letter_t,1,3);
  digitalWrite(pinLB,HIGH); // left wheel stop
  digitalWrite(pinRB,HIGH); // right wheel stop
  analogWrite(pinLF,0);
  analogWrite(pinRF,0);
}

void BackRight() // turn right
{
  display.setSegments(Letter_r,1,0);
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB,HIGH);
  digitalWrite(pinRB, LOW); // wheel on the right moves backward
  analogWrite(pinLF,FullSpeed); // from FullSpeed
  analogWrite(pinRF,FullSpeed); // from FullSpeed
}

void BackLeft() // turn left
{
  display.setSegments(Letter_L,1,0);
  display.setSegments(Letter_b,1,1);
  display.setSegments(Letter_A,1,2);
  display.setSegments(Letter_c,1,3);
  digitalWrite(pinLB, LOW); // wheel on the left moves backward
  digitalWrite(pinRB,HIGH);
  analogWrite(pinLF,FullSpeed);
  analogWrite(pinRF,FullSpeed);
}

void loop()
{
labelF:
// --- Forward obstacle detection and moving ---
  angle = 90;
  ask_pin_F(); // Fdistance
  if(Fdistance <= Ls)
  {
    Stopp(); // stop for a while
    goto label2;
  }
  if((Fdistance > Ls) & (Fdistance <= Ll))
  {
    MidSpeed();
    goto labelF;
  }
  if(Fdistance > Ll)
  {
    Advance();
    goto labelF;
  }

label2:
  angle = 90; // Check the distance ahead again
  ask_pin_F();
  if(Fdistance < Ls )
  {
    Back(); // go back a little
    if(Fdistance < 30 ) delay( 30);
    if(Fdistance < 20 ) delay( 60);
    if(Fdistance < 10 ) delay(120);
  Stopp();
  }
// Measure left and right space
  angle = 3;
  ask_pin_F();
  Drh=Fdistance;
  delay(700);
  angle = 177;
  ask_pin_F();
  Dlh=Fdistance;
  delay(700);
  angle =90; //added
  ask_pin_F(); // check forward
  Dfr=Fdistance;
  delay(700);

if((Dfr > Dlh) & (Dfr > Drh)) goto labelF; // added
if(Dlh < Drh)
{
  display.setSegments(Letter_LT,1,0);
  delay(1000);
  BackLeft();
  delay(600);
  Stopp();
  delay(400);
  goto labelF;
}
//
else
{
  display.setSegments(Letter_GT,1,0);
  delay(1000);
  BackRight();
  delay(600);
  Stopp();
  delay(400);
  goto labelF;
}
}

void ask_pin_F() // Measure the distance at the specified angle
{
  myServo.write(angle);
  delay(10);
  digitalWrite(PIN_SONAR_TRIGGER,LOW);
  delayMicroseconds(1);
  digitalWrite(PIN_SONAR_TRIGGER,HIGH);
  delayMicroseconds(11);
  digitalWrite(PIN_SONAR_TRIGGER,LOW);
  unsigned long t = pulseIn(PIN_SONAR_ECHO,HIGH);
  unsigned long distance = t*0.017;
  Fdistance = distance;
  if((  89 < angle) & (angle <  91)) display.setSegments(Letter_F,1,0);
  if((    0 < angle) & (angle <  10)) display.setSegments(Letter_r,1,0);
  if(( 170 < angle) & (angle < 180)) display.setSegments(Letter_L,1,0);
  display.showNumberDec(distance / 100,true, 1, 1);
  display.showNumberDec(int( distance - int(distance/100)*100 )/10,false, 1, 2);
  display.showNumberDec(int( distance - int(distance/10)*10 ),false, 1, 3);
  delay(30);
}

08/04/2019

Arduino Tank Robot

Img_20190803_165802 Img_20190803_165720
Img_20190803_165812 Img_20190803_165821
100均セリアで Arduino UNOとMotor Shield が丁度入る カードケースを見つけたので、小型のロボットタンクのシャシーの上に載せてみた。
シャシーとケースとの間は、M3のネジで接合してある。
ボディの前方は、超音波測定器(HC-SR04)を設置し、前方の障害物との距離を計測する。
HC-SR04は、ミニブレッドボードを使い取り付けた。ミニブレッドボードの底面の突起を削って平らにして、サーボモータのアーム部分に両面テープで接着し、表側のピン穴を使ってHC-SR04を差し込み取り付けたのだ。
距離の測定には、「NewPing」ライブラリーを使った。

ロボットが動いている時に「距離をどのように計測し、それから何を判断したか」を、僕が見て分かるようにしたいと思い、TM1637 4桁7セグメント表示器を付けた。 表示器は4桁なので、基本的に、左1桁は、進行方向に対する判断結果表示を、残り3桁は、計測した方向にある障害物との距離をcmで表示するようにした。
このような仕掛けを組み込んだので、不具合発生時、問題の調査が行いやすかった。 

表示内容は、7セグメントでのASCII文字表示に従い表示するようにした。
①前方障害物との距離・・・計測した距離の単位はcmで、3桁で表示
②モーター制御の方向
 前進(1桁目に「F」表示 及び 前方障害物との距離を3桁で表示)、停止(「HALt」と表示)、後退(「bAc」と表示)、左方向へ後退(「LbAc」と表示)、右方向へ後退(「rbAc」と表示)
③左右方向の余裕距離・・・計測した距離の単位はcmで表示
 左側より右側が広く空いている場合は、1桁目に < のASCII文字表示で示し、距離を3桁で表示。
 右側より左側が広く空いている場合には、1桁目に > のASCII文字で示し、同様に距離を3桁で表示した。

 注意)事例として、ロボットが一旦停止して表示する1桁目が「<」の表示の場合は、右側が左側より広く空いているので、左方向にバックしてから直進し、右方向に進む。

部品構成
 Arduino:UNO
 Motor Shield:Rasbee L298P  @591
 Sensor:HC-SR04 超音波センサーモジュール
 ServoMotor:Lemcos MG 996R(メタルギヤ デジタルRCサーボモーター) @480
 Battery:KEEPPOWER IMR 18650サイズ互換 2600mAh リチウムマンガンバッテリー 
 Display:0.36インチ(
42X24X12mm) 4桁7セグメント (ドライブチップはTM1637 )  @188
 本体ケース:100均セリアのカードケース
 シャシー:KKmoon ロボットタンク クローラーシャーシ  @2499
 Switch:オン/オフSPDTミニ2ポジションラッチトグルスイッチ
その他
 Battery充電器:XTAR VC2S USB 急速 電池 マルチサイズ対応 充電器
 基板の固定用として、六角ナットねじスペーサ(長さ10mmのものを使用)
など

本体に入れた頭脳となる基板は、 arduino UNO の上に arduino専用の L298P motor shield を載せた2層構造にしてある。
電池は、カードケースの裏蓋の中に収めることが出来た(両面テープで電池フォルダーを接着)。
カードケース内の高さは、それほど余裕が無いので、ピン端子と干渉しないように注意して配置する必要がある。
接続ピンは、Motor Shieldカードの左右に配置されると思うので、Battery Holder はなるべく中央部に配置するのが良いと思う。
USB端子と電源の両方を使えるように、ケースに穴を開け、ポートアクセスが可能なようにした。
バッテリ電源用ON/OFFスイッチとして、スナップスイッチを設置した。


配線接続について
1)Motor Shield を使う場合には、PWMピンは使用方法に指定があるので、そのように使わないと制御できない。
 (参考:L298P 2-A Dual H-Bridge Motor Shield for Arduino .pdf)
 ①詳細は、上記pdfを確認する事。表にして記載されている。
 ②2つのブラシ付きDCモーターを、本シールドのモーターAとモーターBの端子に接続する事で使用できる。
 ③方向制御AはD12ピン、方向制御BはD13ピンをHIGHまたはLOWにすることで、モーターの方向を制御できる。
 ④D10ピンとD11ピンにより、モーターの速度を制御できる。
 ⑤従って、D10~D13ピンは内部で使われるので、別の目的のピンをD10~D13には接続しない事。
L298p-motor-shield L298poriginal2
Img_20190804_110801 Img_20190804_110734

2)センサー用サーボモーターの接続は、Motor Shield の「SERVO(G +5 9)」と書かれたピン(Pin9)に刺す。
  写真では、G(GND)は、茶色の配線
       +5は、赤色の配線
       9 は、オレンジ色の配線
Img_20190803_165907 Img_20190803_165941

3)超音波センサー(HC-SR04)のピン接続は、Echo-Pin5、Trig-Pin6 に刺す。Motor Shield 側のピン接続部分は、オス用・メス用両方が用意されているのでどちらを使ってもよい。+5V電源とGNDピンは、接続しやすく、バッテリーなどと干渉しない部分を使えばよい。
  写真では、GND は 青色の配線
       Echo 
は 黄色の配線
       Trig は 緑色の配線
       Vcc は 赤色の配線

4)4桁7セグメント表示器の接続は、
 CLK - Pin7(写真では黄色の配線)
 DIO - Pin8(写真ではオレンジの配線)
 VCC - 接続しやすい5V端子へ接続(写真では赤色の配線)
 GND - 接続しやすいGND端子へ接続(写真では茶色の配線)
Img_20190804_110648
 4桁7セグメント表示器のケースへの取り付けは、上の写真のように2本のボルトで止めてある。

5)バッテリー、スイッチ、Motor Shield 外部電源端子間を接続



《Sketch》

// Obstacle avoidance Tank Robot program 2019/08/03
// New algorithm version My Spice Cabinet

#include <NewPing.h>
const int PIN_SONAR_ECHO = 5; // define pin for sensor echo
const int PIN_SONAR_TRIGGER = 6; // define pin for sensor trig
const int MAX_DISTANCE = 200;
NewPing sonar(PIN_SONAR_TRIGGER, PIN_SONAR_ECHO, MAX_DISTANCE);
#include <Servo.h>

#include <TM1637Display.h>
#define CLK 7 //can be any digital pin
#define DIO 8 //can be any digital pin
double Fdistance = 0;
double Dlh;
double Drh;
double Ls = 30; // short range threshold
double Ll = 55; // long range threshold
int angle;
int pinSRB= 9; // servo motor output pin (PWM)

// next pins(10~13) are depended on L298P motorshield
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function from 10
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function

int FullSpeed = 255; // max 255
int HalfSpeed = 233;
Servo myServo; // set myservo

TM1637Display display(CLK, DIO);
const uint8_t Letter_F[] = { SEG_A | SEG_E | SEG_F | SEG_G };              // F
const uint8_t Letter_b[] = { SEG_C | SEG_D | SEG_E | SEG_F | SEG_G }; // b
const uint8_t Letter_H[] = { SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // H
const uint8_t Letter_r[] = { SEG_E | SEG_G };              // r
const uint8_t Letter_L[] = { SEG_D | SEG_E | SEG_F }; // L
const uint8_t Letter_A[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G }; // A
const uint8_t Letter_c[] = { SEG_D | SEG_E | SEG_G };             // c
const uint8_t Letter_t[] = { SEG_D | SEG_E | SEG_F | SEG_G }; // t
const uint8_t Letter_LT[] = { SEG_A | SEG_F | SEG_G }; // <
const uint8_t Letter_GT[] = { SEG_A | SEG_B | SEG_G }; // >

void setup()
{
Serial.begin(9600);
display.setBrightness(0x0f);   // 0x01 << dark bright >> 0x0f
display.clear();
// Define motor output pin
pinMode(pinLB,OUTPUT);  // pin 12 direction control function
pinMode(pinLF,OUTPUT);   // pin 10 (PWM)
pinMode(pinRB,OUTPUT);  // pin 13 direction control function
pinMode(pinRF,OUTPUT);   // pin 11 (PWM)
myServo.attach(pinSRB);   // Define servo motor output pin(PWM)
}

void Advance() // move to forward
{
display.setSegments(Letter_F,1,0);
digitalWrite(pinLB,LOW); // left wheel moves forward
digitalWrite(pinRB,LOW); // right wheel moves forward
analogWrite(pinLF,FullSpeed);
analogWrite(pinRF,FullSpeed);
}

void Back() // move backward
{
display.clear();
display.setSegments(Letter_b,1,1);
display.setSegments(Letter_A,1,2);
display.setSegments(Letter_c,1,3);
delay(50);
digitalWrite(pinLB,HIGH);   // motor moves to left rear
digitalWrite(pinRB,HIGH);   // motor moves to right rear
analogWrite(pinLF,FullSpeed);
analogWrite(pinRF,FullSpeed);
}

void MidSpeed() // move to forward
{
display.setSegments(Letter_F,1,0);
digitalWrite(pinLB,LOW);   // left wheel moves forward
digitalWrite(pinRB,LOW);   // right wheel moves forward
analogWrite(pinLF,HalfSpeed);
analogWrite(pinRF,HalfSpeed);
}

void Stopp() // all wheel stop
{
display.setSegments(Letter_H,1,0);
display.setSegments(Letter_A,1,1);
display.setSegments(Letter_L,1,2);
display.setSegments(Letter_t,1,3);
digitalWrite(pinLB,HIGH);   // left wheel stop
digitalWrite(pinRB,HIGH);   // right wheel stop
analogWrite(pinLF,0);
analogWrite(pinRF,0);
}

void BackRight() // turn right
{
display.setSegments(Letter_r,1,0);
display.setSegments(Letter_b,1,1);
display.setSegments(Letter_A,1,2);
display.setSegments(Letter_c,1,3);
digitalWrite(pinLB,HIGH);
digitalWrite(pinRB, LOW);       // wheel on the right moves backward
analogWrite(pinLF,FullSpeed); // from FullSpeed
analogWrite(pinRF,FullSpeed); // from FullSpeed
}

void BackLeft() // turn left
{
display.setSegments(Letter_L,1,0);
display.setSegments(Letter_b,1,1);
display.setSegments(Letter_A,1,2);
display.setSegments(Letter_c,1,3);
digitalWrite(pinLB, LOW);   // wheel on the left moves backward
digitalWrite(pinRB,HIGH);
analogWrite(pinLF,FullSpeed);
analogWrite(pinRF,FullSpeed);
}

void loop()
{
labelF:
// --- Forward obstacle detection and moving ---
angle = 90;
ask_pin_F();   // Fdistance
if(Fdistance <= Ls)
{
Stopp();         // stop for a while
goto label2;
}
if((Fdistance > Ls) & (Fdistance <= Ll))
{
MidSpeed();
goto labelF;
}
if(Fdistance > Ll)
{
Advance();
goto labelF;
}

label2:
angle = 90;   // Check the distance ahead again
ask_pin_F();
if(Fdistance < Ls )
{
  Back();         // go back a little
  if(Fdistance < 30 ) delay( 50);
  if(Fdistance < 20 ) delay(100);
  if(Fdistance < 10 ) delay(100);
  Stopp();
}
// Measure left and right space
angle = 3;
ask_pin_F();
Dlh=Fdistance;
angle = 177;
ask_pin_F();
Drh=Fdistance;

 

if(Dlh < Drh)
{
display.setSegments(Letter_LT,1,0);
delay(1000);
BackLeft();
delay(600);
Stopp();
delay(400);
goto labelF;
}
//
else
{
display.setSegments(Letter_GT,1,0);
delay(1000);
BackRight();
delay(600);
Stopp();
delay(400);
goto labelF;
}
}

void ask_pin_F()   // Measure the distance at the specified angle
{
myServo.write(angle);
delay(10);
unsigned long microSec = sonar.ping_median();
unsigned long distance = sonar.convert_cm(microSec);
Fdistance = distance;
display.showNumberDec(distance / 100,true, 1, 1);
display.showNumberDec(int( distance - int(distance/100)*100 )/10,false, 1, 2);
display.showNumberDec(int( distance - int(distance/10)*10 ),false, 1, 3);
delay(30);
}

《備考》
参考としたブログなど
1)http://www.handsontec.com/dataspecs/arduino-shield/L298P%20Motor%20Shield.pdf
  L298P Motor Shield の使い方のマニュアル

2)https://iot.keicode.com/arduino/arduino-sonar-hc-sr04.php
  超音波センサーの使い方 NewPing の使い方など

《あとがき》
 前回のブログでは、Motor Shield に問題があって中断とした。既に廃却してしまったので検証は出来ないが、もしかすると、モータを低速で回転させたいと思って選んだ制御用数値が、使えない範囲のものを選んだ可能性が高い。また、L298P Motor Shield はPWMピンとして使えるものが、前述の配線接続についての項目の最初の絵にある表のように指定されているので、それを守らないと制御できない。
 超音波センサーの位置が高い場所に設置してしまった事と、シャシーの幅が広いので・・・(低い位置に設置する良いアイデアが思い浮かばなかったので・・・)時々、低い場所にある障害物に衝突して、動けなくなることがある。Sketchを改善するかセンサーの位置を変更するなどする必要がありそう
 Sketchの中で「l(Lの小文字)」と「|(理論和の記号)」の違いが分かりにくいが、Sketch の中で「|(理論和の記号)」を使っているのは、TM1637のDisplay設定の中だけである。他の部分は全てLの小文字「l」である。
 LsとLlの閾値を変えると、タンクの挙動も大きく変わってくる。遊ばれる環境で数値を変えてみるといい。
 前回記載のタンクロボットは、Sketchも含めて今回のものに改新したので、前回のブログも抹消する事にした。

07/09/2019

Arduino NANO を使って BME280 で計測し LCD(16x2) に表示する

Img_20190709_121953 Img_20190709_122102
Arduino NANO を使って BME280 で、温度・湿度・気圧を計測し、結果を LCD(16x2) に表示する。
当初、LCD(16x2)の使い方が分からないので、ブログの簡単な事例でトライアルしてみたが、正しいはずの Sketch で、エラー無くコンパイルされたのに、画面は真っ白のまま・・・何故なのだろうと調べた挙句、LCD裏面の可変抵抗を調整して画面の明るさを加減しないと、表示された文字が見えないという事が分かった。わかってしまえば簡単な事なのに・・・、それで表示問題は解決。

BME280 と LCD どちらも I2C で接続するにはどうすれば良いのか・・・と悩んでいたが、BME280 は SPI 接続し、LCD は I2C 接続する方法で試したら上手くできた。Arduino NANO との接続方法は、下記の Sketch の中に書き入れた。

LCD は2行表示なので、温度、湿度、気圧を同時に表示することは出来ない。 2行を使い3行分のデータを順にまわして表示するか・・・とも考えたが、Sketchが面倒なので、温度表示は固定し、湿度と気圧を 3秒毎に上書き表示するようにしてみた。1行分のデータを、それぞれめいっぱい使えば、上書き時に完全に置き換えが出来る。

シリアルモニターにも表示できるようにしておいた。

という事で、スケッチは下記のようにすれば、完成!

【注記】表示されている温度と湿度に関していえば、温度は2℃ほど高めに表示されるし、湿度は10%ほど低めに表示されるようだ。
 気圧に関しても正確な値を表示していないかもしれない。それぞれ補正出来れば良いのですが・・・

《Sketch》
// Even though the sketch is correct,
// the text can not be seen without adjusting the LCD contrast.
// BME280 --- Arduino NANO (SPI connection)
//      CSB --- D10
//      SDA --- D11
//      SDO --- D12
//      SCL --- D13
// LCD(16x2) --- Arduino NANO (I2C connection)
//         GND --- GND
//         VCC --- 5V
//         SDA --- A4
//         SCL --- A5

#include <Wire.h>
#include "SparkFunBME280.h"
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR  0x3F
LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);  // I2C: 0x3F, 16x2 LCD
const int SPI_CS_PIN = 10;
BME280 sensor;

void setup() {
lcd.init();
lcd.backlight();
Serial.begin(115200);
Wire.begin();
sensor.beginSPI(SPI_CS_PIN);
}

void loop() {
Serial.print("Temp: ");
Serial.print(sensor.readTempC(), 2);
Serial.print(" °C, Humidity: ");
Serial.print(sensor.readFloatHumidity(), 2);
Serial.print(" %, Pressure: ");
Serial.print(sensor.readFloatPressure() / 100.0, 1);
Serial.println(" hPa");

lcd.setCursor(0, 0);
lcd.print("Temp. " + String(sensor.readTempC()) + " deg");
lcd.setCursor(0, 1);
lcd.print("Humid. " + String(sensor.readFloatHumidity()) + " % ");
delay(3000);
lcd.setCursor(0, 1);
lcd.print("Prs. " + String(sensor.readFloatPressure()/ 100.0) + " hPa");
delay(3000);
}

07/07/2019

玄関先にある郵便受けが開いた回数を表示する

Img_20190707_163620 Img_20190707_163717  
前回作成したタクトスイッチを押した回数を表示する装置を利用して、玄関先に設置の郵便受けが開いた回数を表示するようにした。
郵便受けが開いたことを知らせる装置は、「ポストに郵便物が入ったらLEDを点灯するには・・・3(2016/12/6)」の記事などを参考に見て戴きたい。
右側装置の時計表示の上側にある部分は、郵便受けが開いたという信号を受けるもので、受信した信号を、フォトカプラを使って左側の装置に2本の線(水色・白色)で信号を送り、回数を8x8ドットマトリックスLEDで表示する。

Tact buttonを押した回数をLED Matrix display 8×8 dots (MAX7219) に表示する

Tact-sw-counter-with-8x8-dot-matrix-dispImg_20190707_125127Img_20190707_132210 タクトボタンを押した回数を、LED Matrix display 8×8 dots に表示させたいと思い作ってみた。
表示器は、8×8 dotsが1つなので、数値は「9」迄しか表示できない。ただし、表示させてみたところ、DOSのマニュアルにあるコードページ437 が使われているので、タクトスイッチを47クリックしてようやく「0」になる。それでカウンターに初期値「48(=0)」を入れ、タクトスイッチが押される毎に、コードを進めて、カウント文字を表示することにした。
int icount = 48;
となっているのは、このためであり、Matrix display に「0」と表示させるための小技である。
従って、タクトボタンを押す回数が進めば、表示は数字ではなく、コード表にある文字に変わってゆく。
いまのところ、これを使う表示では、数値が2桁になることは無いだろうと思っているが、カウント数が増えれば、表示方法も考える必要がある。

部品は下記のとおり。
① LED Matrix display 8×8 dots ・・・ amazon で 購入 @257
② Arduino NANO ・・・ amazon で 購入
③ tact button
④ 単線cable

1)LED Matrix display 8×8 dots は、私がブレッドボードに取り付けたい方向にピン差し込み部分が無いので、
ピンの曲がりをラジオペンチで直して、半田ごてを使ってピンの半田を溶かしながら、素早くスライドさせて、ブレッドボードに差し込めるようにした。
ブレッドボード上の配線は、ブレッドボードに這わせるように引いたので、線の繋がりが見えにくいかもしれない。

Matrix display の各端子とArduinoのピンとの接続は下記のように行った。

Matrix Display    Arduino NANO
VCC ・・・・・・・・・ 5V
GND ・・・・・・・・・ GND
DIN ・・・・・・・・・ D11
CS  ・・・・・・・・・ D10
CLK ・・・・・・・・・ D13

Tact Switch
左下pin ・・・・・・・ D7
左上pin ・・・・・・・ GND

2)タクトボタンを押すと、チャタリングが入ってしまい、数値が順に表示されなくなるので、
 gazettelabo「●arduino(アルディーノ) 押しボタンスイッチ」を参考にさせて戴き、チャタリング対策を行った。

3) 表示をリセットするには、Arduino NANO の中央部にある「RESET」を押せば、再起動して、表示もゼロからカウントするので、それで良しとした。

その他、ディスプレイ表示では、データが文字(character)でないとダメなので、カウントしている数値(numeric)を文字に変換する方法で手間取った。ようやく文字に変えたつもりが、表示された文字は、ASCIIのIBMコードになっている! それで、数値を示すコードに変更するために、カウント値に 48を加える必要があった。


《sketch》


// http://euc.jp/i18n/charcode.ja.html for character code
// http://gazettelabo.seesaa.net/article/447403643.html
// Reset should be push on reset button on Arduino NANO
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
const int numberOfHorizontalDisplays = 1;
const int numberOfVerticalDisplays = 1;
const int pinCS = 10; // Cs - SS (Pin 10)
// Din - Mosi (Pin 11)
// Clk - Sck (Pin 13)
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
const int wait = 50;
const int count = 7;
int icount = 48;
char c;

void setup() {
matrix.setIntensity( 1 ) ; // Adjust the brightness between 0 and 15
matrix.setPosition( 0, 3, 0) ;
matrix.setRotation( 0, 3) ; // rotation position
Serial.begin(9600);
pinMode(count, INPUT_PULLUP);
matrix.fillScreen(LOW);
c = char(icount);
matrix.drawChar( 2, 1, c, HIGH, LOW, 1);
matrix.write();
}

void loop() {
if ( digitalRead ( count ) == 1)
icount = icount + 1 ;
while ( digitalRead ( count ) == 1) {
delay (wait);
}
c = char(icount);
Serial.print("icount ");
Serial.print(icount);
Serial.print(" = ");
Serial.println(c);

matrix.drawChar( 2, 1, c, HIGH, LOW, 1);
matrix.write(); // Send bitmap to display
delay(wait);
}



06/23/2019

ナレーション入りの音楽からナレーションを抜き出す

Kirin音楽に乗った調子のよいナレーションを見つけた。

キリン メッツ「超ラジオ体操 第一」  藤森くんのチャラいラップも、ゴールドのジャージの「あっちゃん」も、かっこいいです!

それで、自分が通う運動ジムで「ナレーションだけでも覚えて、使いたい!」と思ったが・・・、とても自分が口頭で言うのは無理そうなので、音楽のナレーション部分を抜き出せないか・・・と調べてみた。

最初に見つけた方法は、音楽編集ソフト「Audacity」を使う方法だったが、説明にある通りに進めて・・・ところが・・・途中から表示されるメニューが違う! 
何かが違っていて、自分のやり方に問題があるのかもしれないが、あるところで行き詰ってしまうので、別の方法を探してみることにした。

その方法は、絵にある『「音キりす」v1.0』を使った方法。これは、Windows10でも使えた!
純粋にナレーションのみを抜き出す事は出来なかったが、かなり高いレベルでナレーションを引き出すことができた。

まず、音楽ファイルは、Waveファイルにしておく必要がある。
ファイルを指定した後、左画面の下にある再生ボタン「▶」を押して、再生音楽を聴きながら、そこから切り出すナレーションの音質などを、周波数と音の定位枠(マゼンタ色の枠)を調整しながら(GUIで簡単に)切り出す音の調整を行うことができる。

表示されるドットが 赤色->黄色 となるほど強い音を示している。

納得できる切り出し範囲を決めた後、ファイルを保存して・・・保存したファイルを再生してみた! いい感じで保存できている。

06/18/2019

Arduinoでトイレの電気消し忘れ注意喚起

  Photo時々、トイレの電気を消し忘れている事がある。PIRでモーション検知して電灯をON/OFFする方法もあるが、利用中に突然電灯が消えるという可能性もある。
トイレの電灯を消し忘れた状態では、モーションが検知されず、室内は明るい状態にある。この時に注意喚起音を流せば、この音に気づいて、消灯するだろうと思い、Arduino NANO を使って、

簡単な回路を作ってみた。

システムのチェック用のために、LEDを2つ追加した。
左側は、PIRセンサーの動作確認用で、PIRセンサーがモーションを検知すると点灯する。右側のLEDは、電灯が消えている時に点灯する。
LEDに流れる電流が多くて、ブレッドボード基盤周りが少し熱を持つので、適当な抵抗を入れて電流制限するのが良さそうだ。

必要なセンサーは、部屋の明るさ用にCDR、モーション検知用にPIRの2つ。どちらも手元にあったものを使った。

この状態で暫く使ってみて、動作が良くないようなら、Sketchの中の常数を少し変えてみよう・・・

半日後 ・・・ 状況検出がうまくいっていないので、主に Loop部の Sketchを下記のように書き直した。

ところが・・・使ってみると、夜間、トイレの電気を点灯すると、ブザーが鳴ってしまう! この警報はうるさいなぁ~これを回避しないと、実用とするのは如何なものか・・・ 悩ましい。

《Sketch》

#define LDRpin A0 // this LDR detect the brightness in the room
const int buzzPin = 9;
const int blight = 700; // the threshold value of brightness
int LDRValue = 0; // for read the LDR analog pin
int darkled = 12; // to check darkness
int pirled = 6; // to check motion detection
int pirsensor= 2; // PIR sensor pin
int pirval = 0;
int state = LOW;

void setup() {
Serial.begin(9600); // sets serial port for communication
pinMode(darkled, OUTPUT); // initalize LED as an output
pinMode( pirled, OUTPUT);
pinMode(pirsensor, INPUT); // initialize sensor as an input
pinMode(buzzPin, OUTPUT); // alarm
}

void loop() {
LDRValue = analogRead(LDRpin); // read the value from the LDR
Serial.print("LDR Value = ");
Serial.println(LDRValue); // print the value to the serial port
pirval = digitalRead(pirsensor); // read sensor value
if(LDRValue > blight )
{
digitalWrite(darkled, LOW);
if( pirval == LOW ) // the motion is not detected
{
digitalWrite(pirled, LOW);
// Makes pulses
for(int x = 0; x < 1000; x++) {
digitalWrite(buzzPin,HIGH);
delayMicroseconds(130);
digitalWrite(buzzPin,LOW);
delayMicroseconds(130);
}
delay(300);
}
if ( pirval == HIGH ) // human is in the room
{
digitalWrite(pirled, HIGH);
Serial.println("Motion detected!");
delay(30000);
}
}
if(LDRValue <= blight )
{
digitalWrite(darkled, HIGH);
}
state = LOW;
digitalWrite( pirled, LOW);
digitalWrite(buzzPin, LOW);
digitalWrite(darkled, LOW);
}

 

06/12/2019

4-8x8 dot matrix Clock drive by Arduino NANO and GPS

Gpsfritzing3
 4連 8x8 dot matrix LED の Lチカが上手くできたので、GPSを追加して時計を作ってみた。


 Fritzingを使った、8x8 dot matrix LED、GPS、Arduino  NANOの結線状態は、図のようである。

 LEDとGPSに関して、ここで使った部品の Fritzing 画像をネット上で探したが、見つからなかったので、類似部品を使って結線図を作成した。



私が使った部品
は、
・4連 8x8 dot matrix LED : SODIAL(R) 4イン1ドットマトリクスMCU LEDディスプレイモジュールDIYセット
                                       価格 @589 (Amazon から購入)
・GPS unit : GPS受信機キット 1PPS出力付き 「みちびき」3機受信対応 [AE-GYSFDMAXB]
                   価格 @2100(秋月電子通商から購入)
・Arduino NANO 

GPSユニットは、Fritzingで使ったような、価格の安価なものでも利用できるのではないかと思う。
図のように結線し、下記のSketchで稼働させればよい。クリックすれば、画像を拡 大できるブログエディタの機能がどこにあるのか分からない・・・(ココログの新エディタ、使いにくい!)

そのため、結線方法をここに記載しておく(Sketchの中にも記載しておいたが・・・)

Arduino NANO      GPS
D3  ------------------  TXD
D4  ------------------  RXD
GND  ----------------  GND
5V  ------------------  5V

Arduino NANO      Max7219
D10  -----------------  CS
D11  -----------------  DIN
D13  -----------------  CLK
GND  ----------------  GND
5V  ------------------  VCC

Sketchでちょっと苦労したのは、午前0時から9時までのように、1桁になってしまう時刻の表示。加えて、時計が稼働していることを示す方法。

・1桁になる時刻は、GPSから受け取った「時(hour)」の桁数を読んで、1桁の場合には、スペース(” ”)を入れ、表示させることにした。(一般的な処置方法は、10以上か否かという数値の処理で行われている。) 僕は、文字の桁数で処理することにして、「分(minute)」の方は、ゼロ(”0”)を入れて表示させるようにした。
 ただし、Serial.print で表示させる displayTime() のところは、引用した Sketch のまま変更していない。
 displayDate() についても、引用した Sketch のまま変更していない。
 ドットマトリックス表示には無関係なので、消してもよかったのだが、あとで Serial.print する際のことを考慮して残した。
・時計の稼働は、「時」と「分」の間の「:」を点滅させることで、動いていることを表示させるようにした。

《参考としたブログなど》
MAX7219 Arduino Clock  (instructables circuits より)



《Sketch》

// GPS Clock with MAX7219 8x8 display  2019/06/12  << My Spice Cabinet >>
#include <TinyGPS++.h> // Include the TinyGPS++ library
#include <SoftwareSerial.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
TinyGPSPlus tinyGPS;  // Create a TinyGPSPlus object
#define GPSBaud 9600 // GPS module baud rate. defaults to 9600
#define ARDUINO_GPS_RX 4 // GPS TX, Arduino RX pin
#define ARDUINO_GPS_TX 3 // GPS RX, Arduino TX pin
SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX);
#define gpsPort ssGPS // Alternatively, use Serial1 on the Leonardo
#define SerialMonitor Serial
const byte PIN_CLK = 13;   // define CLK pin (any digital pin)
const byte PIN_DIO = 11; // define DIO pin (any digital pin)
int pinCS = 10; // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
int numberOfHorizontalDisplays = 4;
int numberOfVerticalDisplays = 1;
int wait = 70; // In milliseconds
int spacer = 1;
int Y0 = 0; // if Y0=0 then
int jpt;
int width = 5 + spacer; // The font width is 5 pixels
char time_value[20];
String s;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
void setup()
{
gpsPort.begin(GPSBaud);
SerialMonitor.begin(115200);
matrix.setIntensity(10); // Use a value between 0 and 15 for brightness
matrix.setPosition( 0, 3, 0) ; // The first display is at <0, 0>
matrix.setPosition( 1, 2, 0) ; // The second display is at <1, 0>
matrix.setPosition( 2, 1, 0) ; // The third display is at <2, 0>
matrix.setPosition( 3, 0, 0) ; // The fourth display is at <3, 0>
matrix.setRotation(0, 1); // The first display is position upside down
matrix.setRotation(1, 1); // The first display is position upside down
matrix.setRotation(2, 1); // The first display is position upside down
matrix.setRotation(3, 1); // The first display is position upside down
delay(1000);
}
void loop()
{
// print position, altitude, speed, time/date, and satellites:
displayInfo();
// "Smart delay" looks for GPS data while the Arduino's not doing anything else
smartDelay(1000);
}
void displayInfo()
{
// Print latitude, longitude, altitude in feet, course, speed, date, time,
// and the number of visible satellites.
SerialMonitor.print("Lat: "); SerialMonitor.println(tinyGPS.location.lat(), 6);
SerialMonitor.print("Long: "); SerialMonitor.println(tinyGPS.location.lng(), 6);
SerialMonitor.print("Alt: "); SerialMonitor.println(tinyGPS.altitude.feet());
SerialMonitor.print("Course: "); SerialMonitor.println(tinyGPS.course.deg());
SerialMonitor.print("Speed: "); SerialMonitor.println(tinyGPS.speed.mph());
SerialMonitor.print("Date: "); displayDate();
SerialMonitor.print("Time: "); displayTime();
SerialMonitor.print("Sats: "); SerialMonitor.println(tinyGPS.satellites.value());
SerialMonitor.println();
jpt = tinyGPS.time.hour() + 9;
if( jpt >= 24 ) jpt = jpt - 24;
s=String(jpt);
if( s.length() == 1 )
{
s = " " + s;
time_value[0]= s.charAt(0);
time_value[1]= s.charAt(1);
}
else
{
time_value[0]= s.charAt(0);
time_value[1]= s.charAt(1);
}
s=String(tinyGPS.time.minute() );
if( s.length() == 1 )
{
s = "0" + s;
time_value[3]= s.charAt(0);
time_value[4]= s.charAt(1);
}
else
{
time_value[3]= s.charAt(0);
time_value[4]= s.charAt(1);
}
matrix.fillScreen(LOW);
matrix.drawChar( 2, Y0, time_value[0], HIGH,LOW,1);
matrix.drawChar( 8, Y0, time_value[1], HIGH,LOW,1);
// matrix.drawChar(14, Y0, 58, HIGH,LOW,1); // Fixed 58(ASCII Code) = ":"
matrix.drawChar(20, Y0, time_value[3], HIGH,LOW,1);
matrix.drawChar(26, Y0, time_value[4], HIGH,LOW,1);
matrix.write(); // Send bitmap to display
delay(1000);
matrix.drawChar(14,0, 58, HIGH,LOW,1); // blinking 58(ASCII Code) = ":"
matrix.write(); // Send bitmap to display
}
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
// If data has come in from the GPS module
while (gpsPort.available())
tinyGPS.encode(gpsPort.read()); // Send it to the encode function
// tinyGPS.encode(char) continues to "load" the tinGPS object with new
// data coming in from the GPS module. As full NMEA strings begin to come in
// the tinyGPS library will be able to start parsing them for pertinent info
} while (millis() - start < ms);
}
// printDate() formats the date into dd/mm/yy.
void displayDate()
{
SerialMonitor.print(tinyGPS.date.day());
SerialMonitor.print("/");
SerialMonitor.print(tinyGPS.date.month());
SerialMonitor.print("/");
SerialMonitor.println(tinyGPS.date.year());
}
// printTime() formats the time into "hh:mm:ss", and prints leading 0's
// where they're called for.
void displayTime()
{
SerialMonitor.print(tinyGPS.time.hour()+9);
SerialMonitor.print(":");

if (tinyGPS.time.minute() < 10) SerialMonitor.print('0');
SerialMonitor.print(tinyGPS.time.minute());
SerialMonitor.print(":");
if (tinyGPS.time.second() < 10) SerialMonitor.print('0');
SerialMonitor.println(tinyGPS.time.second());
}

06/11/2019

Arduino で 4-8x8 dotmatrix LED使用方法(いわゆるLチカ)

4-8x8ドットマトリックスLEDで時刻表示を行いたいが、私が理解しやすい方法がなかなか見つからなかった。
直接に時計表示では、何が問題でうまくできないのかが明確に分からないので、単純にLED表示だけを行って、やり方を確認することにした。

参考にしたのは「8×32 LED Matrix MAX7219 Tutorial with Scrolling Text」というブログ。ここでは、4つの8x8ドットLEDマトリックスに対して、設定した文字列を左右方向に流すもの。私は、まず固定表示で、表示方法を確認するのが目的なので、そこに書かれているスケッチから、私の目的に対し不要なものは削って、なるべく最小限のスケッチで、8x8ドットマトリックスの表示を使うには、どうすれば良いかを探ってみた。

下記のスケッチでは、文字列「23:56」を表示させるもので、使っているフォントの1文字の幅は5dotである。表示装置の横幅は、32dotあるので、「23:56」が形よく表示されるように、各文字の表示位置を下記のように少し修正している。

matrix.drawChar( 1, 0, string[0], HIGH, LOW, 1);
matrix.drawChar( 8, 0, string[1], HIGH, LOW, 1);
matrix.drawChar(13, 0, string[2], HIGH, LOW, 1);
matrix.drawChar(18, 0, string[3], HIGH, LOW, 1);
matrix.drawChar(25, 0, string[4], HIGH, LOW, 1);


左端に位置する「2」と、右端に表示する「6」の表示バランスを考え、左側には1列分、右側には2列分を空けることにした。
各文字のX方向の開始位置は、上記のスケッチのように 1,8,13,18,25 とした。そうすると、「2」「3」「:」「5」「6」の各文字の間には、それぞれ2ドット分の空きができる。

フォントの高さは7ドットなので、Y方向は「0」とした。その結果、表示の下の行には、無表示の部分ができる。
もし、文字の上部側に無表示のドットスペースを置くのなら、Y方向は「1」とすればよい。

注意しなければいけない事として、matrix.setPosition の書き方があるように思う。

matrix.setPosition( 0, 3, 0) ; // The first display is at <0, 0>
matrix.setPosition( 1, 2, 0) ; // The second display is at <1, 0>
matrix.setPosition( 2, 1, 0) ; // The third display is at <2, 0>
matrix.setPosition( 3, 0, 0) ; // The fourth display is at <3, 0>


ブログからサンプルとしたものでは、文字が乱れて、どのように並んでいるのか、良くわからない状態だった。
僕は表示させる文字列を「1234」として、表示がどのように並ぶかを確認してみた。
その結果、サンプルのものでは「4321」と並んでいることが分かったので、上記に取り出したサンプルのように、2列目の番号を入れ替えた。


パーツの接続方法
Arduino NANO       MAX7219
5V  ---------------- VCC : 写真では「黄色」
GND --------------- GND : 写真では「緑色」
D11 --------------- DIN : 写真では「青色」
D10 --------------- CS : 写真では「紫色」
D13 --------------- CLK : 写真では「灰色」

使用した部品類
・8x32 LED MAX7219 Dot Matrix Module 
・Arduino NANO
・ブレッドボード

配線図・写真
    

Sketch (Source Code)

#include  <Adafruit_GFX.h>
#include <Max72xxPanel.h>
// Vcc - Vcc
// Gnd - Gnd
// Din - Mosi (Pin 11)
// Cs - SS (Pin 10)
// Clk - Sck (Pin 13)
const int pinCS = 10;
const int numberOfHorizontalDisplays = 4;
const int numberOfVerticalDisplays = 1;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
const int wait = 50;
const int spacer = 1;
const int width = 5 + spacer;
void setup(){
matrix.setIntensity( 1 ) ; // Adjust the brightness between 0 and 15
matrix.setPosition( 0, 3, 0) ; // The first display is at <0, 0>
matrix.setPosition( 1, 2, 0) ; // The second display is at <1, 0>
matrix.setPosition( 2, 1, 0) ; // The third display is at <2, 0>
matrix.setPosition( 3, 0, 0) ; // The fourth display is at <3, 0>
   matrix.setRotation( 0, 1) ;     // Display position
matrix.setRotation( 1, 1) ; // Display position
matrix.setRotation( 2, 1) ; // Display position
matrix.setRotation( 3, 1) ; // Display position
}
void loop(){
String string = "23:56";
matrix.fillScreen(LOW);
matrix.drawChar( 1, 0, string[0], HIGH, LOW, 1);
matrix.drawChar( 8, 0, string[1], HIGH, LOW, 1);
matrix.drawChar(13, 0, string[2], HIGH, LOW, 1);
matrix.drawChar(18, 0, string[3], HIGH, LOW, 1);
matrix.drawChar(25, 0, string[4], HIGH, LOW, 1);
matrix.write(); // Send bitmap to display
delay(wait);
}


参考としたブログ
https://earthbondhon.com/8x32-led-matrix-max7219-tutorial-with-scrolling-text/
 ここに書かれていたコードは、4つのマトリックスモジュールに対して文字列を流れるように表示するもの。

06/05/2019

Arduino UNO 超音波センサーロボットカーに後方センサーを追加

前回製作したArduino UNOのロボットカーでは、後退する際に、障害物に衝突してしまうケースが多発した。
それで、超音波距離センサーを後方にも追加(サーボコントロール無し)して、後方への衝突をできる限り回避するようにしてみた。
後方距離センサー用のピンは、トリガーピンをArduinoのD8に、エコーピンをD7に接続した。
スケッチは次のように加筆変更した。

I made my own robot tank that avoids and moves obstacles.
This robot tank uses an ultrasonic distance sensor that mounted in front of it to measure the distance to an obstacle and control the movement to move.
Since the processing power of the microcomputer is Arduino UNO that is not so high performance, it might be difficult to make a further advanced control. I added a sensor at the back of the tank to measure the distance to the obstacle behind it, so the robot tank can move around in a narrow place without collision.

《Sketch》

// Obstacle avoidance Tank Robot program 2019/06/05
// add backward sensor avoid collisions My Spice Cabinet
double Fdistance = 0;
double Rdistance1= 0;
double Ldistance1= 0;
double Rdistance2= 0;
double Ldistance2= 0;
double RRdist=0;
#include  <Servo.h>
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function
int echoPin = 5; // define pin for sensor echo
int trigPin = 6; // define pin for sensor trig
int echoPinB = 7; // define pin for back sensor echo
int trigPinB = 8; // define pin for back sensor trig
int motorOnTime1; // motor on time back
int motorOnTime2; // turning motor on time
int directionn = 0; // forward=8 backward=2 left=4 right=6
Servo myServo; // set myservo
int delay_time = 250; // settling time 250 after steering servo motor moving B
int Fgo = 8; // Move Forward
int Rgo = 6; // move to the R
int Lgo = 4; // move to the L
int Bgo = 2; // move Backward
int angle;
void setup()
{
Serial.begin(9600);
pinMode(3, OUTPUT); // Head light
// Define motor output pin
pinMode(pinLB,OUTPUT); // pin 12 direction control function
pinMode(pinLF,OUTPUT); // pin 10 (PWM)
pinMode(pinRB,OUTPUT); // pin 13 direction control function
pinMode(pinRF,OUTPUT); // pin 11 (PWM)
// Define Front sensor pin
pinMode(echoPin, INPUT); // define input pin from sensor
pinMode(trigPin,OUTPUT); // define output pin for sensor
// Define Back sensor pin
pinMode(echoPinB, INPUT); // define input pin from sensor
pinMode(trigPinB,OUTPUT); // define output pin for sensor
myServo.attach(9); // Define servo motor output pin to D9 (PWM)
}
void advance()              // move to forward
{
digitalWrite(pinLB,LOW); // left wheel moves forward
digitalWrite(pinRB,LOW); // right wheel moves forward
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void stopp()                // all wheel stop
{
digitalWrite(pinLB,HIGH); // left wheel stop
digitalWrite(pinRB,HIGH); // right wheel stop
analogWrite(pinLF,0);
analogWrite(pinRF,0);
}
void right()                // turn right (single wheel)
{
digitalWrite(pinLB,HIGH); // wheel on the left stop
digitalWrite(pinRB, LOW); // wheel on the right moves backward
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void left()                 // turn left (single wheel)
{
digitalWrite(pinLB, LOW); // wheel on the left moves backward
digitalWrite(pinRB,HIGH); // wheel on the right stop
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void back()                 // move backward
{
digitalWrite(pinLB,HIGH); // motor moves to left rear
digitalWrite(pinRB,HIGH); // motor moves to right rear
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void detection()            // measure multi directions
{
angle = 90; // measure front direction
ask_pin_F(); // read the distance ahead
motorOnTime1 = 100;
motorOnTime2 = 200;
// ==========================================================
if(Fdistance < 30) // if distance ahead is <30cm
{
stopp(); // all wheel stop
delay(motorOnTime1);
back(); // move backward for 0.2S
delay(motorOnTime2);
}
// ----------------------------------------------------------
if(Fdistance < 50) // if distance ahead is <50cm
{
stopp(); // all wheel stop
delay(motorOnTime1);
// ==========================================================
angle = 5; // measure left direction
ask_pin_F(); // read distance on the left
Ldistance1 = Fdistance;
motorOnTime1 = 300;
motorOnTime2 = 300; // turn about 100deg, if 120deg --> 600
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 30; // measure left direction
ask_pin_F(); // read distance on the left
Ldistance2 = Fdistance;
motorOnTime1 = 100;
motorOnTime2 = 200;
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 120; // measure right direction
ask_pin_F(); // read distance on the right
Rdistance2 = Fdistance;
motorOnTime1 = 100;
motorOnTime2 = 200;
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 175; // measure right direction
ask_pin_F(); // read distance on the right
Rdistance1 = Fdistance;
motorOnTime1 = 300;
motorOnTime2 = 300; // turn about 100deg, if 120deg --> 600
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
if(Ldistance2 > Rdistance2) // if LH distance is >distance on the right
{
directionn = Lgo; // move to the L
}
// ----------------------------------------------------------
if(Ldistance2 <= Rdistance2) // if LH distance is <= distance on the right
{
directionn = Rgo; // move to the right
}
// ----------------------------------------------------------
if (Ldistance1 < 30 && Rdistance1 < 30) // if distance on LH and RH are both <30cm
{
directionn = Bgo; // move to backward
ask_pin_B();
}
}
// ----------------------------------------------------------
else // if distance ahead is >50cm
{
angle = 90;
ask_pin_F(); // read the distance ahead
directionn = Fgo; // move forward
}
}
void ask_pin_F()        // measure the distance ahead on the angle
{
myServo.write(angle);
delay(delay_time);
digitalWrite(trigPin, LOW); // ultrasonic sensor transmit low level signal 2μs
delayMicroseconds(2);
digitalWrite(trigPin,HIGH); // ultrasonic sensor transmit high level signal 10μs, at least 10μs
delayMicroseconds(10);
digitalWrite(trigPin, LOW); // keep transmitting low level signal
double Duration = pulseIn(echoPin, HIGH); // read the time in between
Fdistance = Duration/2*340*100/1000000; // convert time into distance (unit: cm)
// debugging the angle and its distance
Serial.print(angle);
Serial.print("- Distance ahead ");
Serial.print(Fdistance);
Serial.println(" [cm]");
}
void ask_pin_B()        // measure the distance backward
{
digitalWrite(trigPinB, LOW); // ultrasonic sensor transmit low level signal 2μs
delayMicroseconds(2);
digitalWrite(trigPinB,HIGH); // ultrasonic sensor transmit high level signal 10μs, at least 10μs
delayMicroseconds(10);
digitalWrite(trigPinB, LOW); // keep transmitting low level signal
double Duration = pulseIn(echoPinB, HIGH); // read the time in between
RRdist = Duration/2*340*100/1000000; // convert time into distance (unit: cm)
// debugging the angle and its distance
Serial.print("Distance backward ");
Serial.print(RRdist);
Serial.println(" [cm]");
}
void loop()
{
// Head light
Serial.print("CDS Value = ");
Serial.println(analogRead(0));
digitalWrite(3, LOW);
if(analogRead(0)<400) digitalWrite(3, HIGH);
// driving forward ----------------------------
angle=90;
myServo.write(angle); // home set the servo motor, ready for next measurement from 90
detection(); // measure the angle and determine which direction to move
if(directionn == 2) // if direction => backward
{
if(RRdist > 25)
{
back(); // go backward
delay(motorOnTime1);
left(); // Move slightly to the left (to prevent stuck in dead end)
delay(motorOnTime2);
}
else
{
stopp();
delay(motorOnTime2);
}
}
// ---------------------------------------------
if(directionn == 6) // if direction => right
{
back(); // go backward
delay(motorOnTime1);
left(); // turn left because reverse driving
delay(motorOnTime2);
}
// ---------------------------------------------
if(directionn == 4) // if direction => left
{
back(); // go backward
delay(motorOnTime1);
right(); // turn right because reverse driving
delay(motorOnTime2);
}
// ---------------------------------------------
if(directionn == 8) // if direction => forward
{
advance(); // move forward
delay(motorOnTime1);
}
}

06/04/2019

Arduino UNO で Robot Car 製作

超音波センサーで周囲のスペースを検知し動き回るタンクロボットを作った。
Img_20190602_085716 Img_20190602_085732 Img_20190602_085744 Img_20190602_085755      
    
使用した部品は、下記の通り
 ①ロボットシャシー:P Prettyia アルミ合金のタンクシャシーをAmazonから購入
 ②Arduino UNO x 1個
 ③超音波距離センサーモジュール:HC-SR04 x 1個
 ④デジタル・マイクロサーボ:SG90 x 1個
 ⑤モータドライバシールド:WINGONEER L298Pモータドライバモジュール
             Arduino用高出力DCステッパモータコントローラ x 1
  https://www.instructables.com/id/Tutorial-for-L298-2Amp-Motor-Driver-Shield-for-Ard/ 
 ⑥Miniブレッドボード:Arduino用170タイポイント Miniブレッドボード x 1個
 ⑦トグルスイッチ x 1
 ⑧18650バッテリー2個用ホルダー x 2個
 ⑨18650バッテリー  x 4個
 ⑩その他、バッテリーを載せるトレイ(100均で調達)、シールド電線少々

・ロボットシャシー:P Prettyia アルミ合金のタンクシャシー は、組立て説明書が添付されず、構成部品だけが送られてくるので、組み上がった写真を見て組立て方法を考える必要がある。送られてきたパーツの数が間違えているのではないかと組立てながら疑った事もあった。キーポイントは、モーター軸に組み付けるハブの組立て状況を写真をよく見て調べることだ。

・モーターを制御するために、僕はWINGONEER のL298Pモーターシールドを使った。
・将来構想として、WiFi あるいは Bluetooth でのラジコンを考えているので、周囲の明るさに応じて、自動的にヘッドライトを点灯する回路を追加した。


《Sketch》

// Obstacle avoidance Tank Robot program 2019/06/04
// My Spice Cabinet http://spice-cabinet.cocolog-nifty.com/blog/
double Fdistance = 0;
double Rdistance1= 0;
double Ldistance1= 0;
double Rdistance2= 0;
double Ldistance2= 0;
#include  <Servo.h>
int pinLB = 12; // direction control function
int pinLF = 10; // motors' control chip with speed control function
int pinRB = 13; // direction control function
int pinRF = 11; // motors' control chip with speed control function
int echoPin = 5; // define pin for sensor echo
int trigPin = 6; // define pin for sensor trig
int motorOnTime1; // motor on time back
int motorOnTime2; // turning motor on time
int directionn = 0; // forward=8 backward=2 left=4 right=6
Servo myServo; // set myservo
int delay_time = 250; // settling time 250 after steering servo motor moving B
int Fgo = 8; // Move Forward
int Rgo = 6; // move to the R
int Lgo = 4; // move to the L
int Bgo = 2; // move Backward
int angle;
void setup()
{
Serial.begin(9600);
pinMode(3, OUTPUT); // Head light
// Define motor output pin
pinMode(pinLB,OUTPUT); // pin 12 direction control function
pinMode(pinLF,OUTPUT); // pin 10 (PWM)
pinMode(pinRB,OUTPUT); // pin 13 direction control function
pinMode(pinRF,OUTPUT); // pin 11 (PWM)
// Define sensor pin
pinMode(echoPin, INPUT); // define input pin from sensor
pinMode(trigPin,OUTPUT); // define output pin for sensor
myServo.attach(9); // Define servo motor output pin to D9 (PWM)
}
void advance()                   // move to forward
{
digitalWrite(pinLB,LOW); // left wheel moves forward
digitalWrite(pinRB,LOW); // right wheel moves forward
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void stopp()                       // all wheel stop
{
digitalWrite(pinLB,HIGH); // left wheel stop
digitalWrite(pinRB,HIGH); // right wheel stop
analogWrite(pinLF,0);
analogWrite(pinRF,0);
}
void right()                       // turn right (single wheel)
{
digitalWrite(pinLB,HIGH); // wheel on the left stop
digitalWrite(pinRB, LOW); // wheel on the right moves backward
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void left()                         // turn left (single wheel)
{
digitalWrite(pinLB, LOW); // wheel on the left moves backward
digitalWrite(pinRB,HIGH); // wheel on the right stop
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void back()                        // move backward
{
digitalWrite(pinLB,HIGH); // motor moves to left rear
digitalWrite(pinRB,HIGH); // motor moves to right rear
analogWrite(pinLF,255);
analogWrite(pinRF,255);
}
void detection()            // measure multi directions
{
angle = 90; // measure front direction
ask_pin_F(); // read the distance ahead
motorOnTime1 = 100;
motorOnTime2 = 200;
// ==========================================================
if(Fdistance < 30) // if distance ahead is <30cm
{
stopp(); // all wheel stop
delay(motorOnTime1);
back(); // move backward for 0.2S
delay(motorOnTime2);
}
// ----------------------------------------------------------
if(Fdistance < 50) // if distance ahead is <50cm
{
stopp(); // all wheel stop
delay(motorOnTime1);
// ==========================================================
angle = 5; // measure left direction
ask_pin_F(); // read distance on the left
Ldistance1 = Fdistance;
motorOnTime1 = 300;
motorOnTime2 = 300; // turn about 100deg, if 120deg --> 600
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 30; // measure left direction
ask_pin_F(); // read distance on the left
Ldistance2 = Fdistance;
motorOnTime1 = 100;
motorOnTime2 = 200;
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 120; // measure right direction
ask_pin_F(); // read distance on the right
Rdistance2 = Fdistance;
motorOnTime1 = 100;
motorOnTime2 = 200;
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
angle = 175; // measure right direction
ask_pin_F(); // read distance on the right
Rdistance1 = Fdistance;
motorOnTime1 = 300;
motorOnTime2 = 300; // turn about 100deg, if 120deg --> 600
delay(delay_time); // stabilizing time for servo motor
// ==========================================================
if(Ldistance2 > Rdistance2) // if LH distance is >distance on the right
{
directionn = Lgo; // move to the L
}
// ----------------------------------------------------------
if(Ldistance2 <= Rdistance2) // if LH distance is <= distance on the right
{
directionn = Rgo; // move to the right
}
// ----------------------------------------------------------
if (Ldistance1 < 30 && Rdistance1 < 30) // if distance on LH and RH are both <30cm
{
directionn = Bgo; // move to backward
}
}
// ----------------------------------------------------------
else // if distance ahead is >50cm
{
angle = 90;
ask_pin_F(); // read the distance ahead
directionn = Fgo; // move forward
}
}
void ask_pin_F()            // measure the distance ahead on the angle
{
myServo.write(angle);
delay(delay_time);
digitalWrite(trigPin, LOW); // ultrasonic sensor transmit low level signal 2μs
delayMicroseconds(2);
digitalWrite(trigPin,HIGH); // ultrasonic sensor transmit high level signal 10μs, at least 10μs
delayMicroseconds(10);
digitalWrite(trigPin, LOW); // keep transmitting low level signal
double Duration = pulseIn(echoPin, HIGH); // read the time in between
Fdistance = Duration/2*340*100/1000000; // convert time into distance (unit: cm)

// debugging the angle and its distance
Serial.print(angle);
Serial.print("- Distance ahead ");
Serial.print(Fdistance);
Serial.println(" [cm]");
}
void loop()
{
// Head light
Serial.print("CDS Value = ");
Serial.println(analogRead(0));
digitalWrite(3, LOW);
if(analogRead(0)<400) digitalWrite(3, HIGH);
// driving forward ----------------------------
angle=90;
myServo.write(angle); // home set the servo motor, ready for next measurement from 90
detection(); // measure the angle and determine which direction to move
if(directionn == 2) // if direction => backward
{
back(); // go backward
delay(motorOnTime1);
left(); // Move slightly to the left (to prevent stuck in dead end)
delay(motorOnTime2);
}
// ---------------------------------------------
if(directionn == 6) // if direction => right
{
back(); // go backward
delay(motorOnTime1);
left(); // turn left because reverse run
delay(motorOnTime2);
}
// ---------------------------------------------
if(directionn == 4) // if direction => left
{
back(); // go backward
delay(motorOnTime1);
right(); // turn right because reverse run
delay(motorOnTime2);
}
// ---------------------------------------------
if(directionn == 8) // if direction => forward
{
advance(); // move forward
delay(motorOnTime1);
}
}



《参考資料》
参考にしたSketch
https://s.siteapi.org/b2a66604b1dde25.ru/docs/1a8777f11b3ec42b322a4659688401e914be7efd.pdf
これを使ったロボットは私のものより少し小さい?ので、モーターを制御するタイミング時間で、動き方がかなり変わっているように思ったので、自分が納得する動きをさせるために、スケッチは大きく変更した。

PWMで明るさを調整できるanalogWrite関数
https://voltechno.com/blog/aruled/

LEDライトのコントロール
https://www.denshi.club/pc/kits/led2arduinol.html
2N7000 x1、75Ω、47KΩ

24 暗くなったらLEDを点滅させる
https://n.mtng.org/ele/arduino/samples/sample24.html
CDS x1、10KΩ

«Arduino UNO で周囲が暗くなったらLEDを点灯する回路

September 2019
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

Recent Trackbacks

無料ブログはココログ