« July 2019 | Main | September 2019 »

August 2019

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

Tank Robotの背中に処理状況を表示

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も含めて今回のものに改新したので、前回のブログも抹消する事にした。

« July 2019 | Main | September 2019 »

July 2020
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 31  

Recent Trackbacks

無料ブログはココログ