以前作った赤外線LEDとフォトトランジスターによるスピード計測はセンサー部が大きくて邪魔なのでホールICを使ったスピード計測を作ってみました。
ホールICを使うので、車両に磁石を付ける必要があります。
回路図は次のようになります。
赤外線LEDが無くなったので、さらにシンプルになってます。
ホールIC(SK8552G-G03-K)は線路の継ぎ目に挟み込む事にします。
車両の下に付ける磁石はセリアで見つけた「超強力マグネット ミニ 8P」を使いました。
スケッチは次のようになります。
#include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 static const unsigned char PROGMEM logo_off[] = { B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B11111111, B11111110, B00000001, B11111110, B00000001, B11111110, B00000001, B11111110, B00000001, B11111110, B00000001, B11111110, B00000001, B11111110, B00000001, B11111110, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000 }; static const unsigned char PROGMEM logo_on[] = { B00000000, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B11111111, B00000000, B10000000, B00000000, B10000000, B00000000, B10000000, B00000000, B10000000, B00000000, B10000000, B00000000, B10000000, B00000000, B10000000, B00000000 }; #define FLAG_ON_VALUE (900) int digitalPin1 = 2; int digitalPin2 = 3; int val1 = 0; int val2 = 0; unsigned char prev_flag1 = 0; unsigned char curr_flag1 = 0; unsigned char chng_flag1 = 0; unsigned char prev_flag2 = 0; unsigned char curr_flag2 = 0; unsigned char chng_flag2 = 0; unsigned char need_draw = 0; unsigned long time0 = 0; unsigned long time1 = 0; unsigned long time2 = 0; float val_speed = 0.0; void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println("SSD1306 OLED 128x64 i2c"); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } // Show initial display buffer contents on the screen -- // the library initializes this with an Adafruit splash screen. display.display(); delay(2000); // Pause for 2 seconds // Clear the buffer display.clearDisplay(); pinMode(digitalPin1, INPUT); pinMode(digitalPin2, INPUT); drawflags(); delay(1000); } void drawbitmap_off(int x, int y) { display.drawBitmap( x, y, logo_off, LOGO_WIDTH, LOGO_HEIGHT, 1); } void drawbitmap_on(int x, int y) { display.drawBitmap( x, y, logo_on, LOGO_WIDTH, LOGO_HEIGHT, 1); } void drawflags() { int x, y; y = LOGO_HEIGHT / 2; //y = (display.height() - LOGO_HEIGHT) / 4; display.clearDisplay(); x = display.width() / 4 - LOGO_WIDTH / 2; if (val1 == HIGH) { drawbitmap_on(x, y); // Draw a small bitmap image } else { drawbitmap_off(x, y); // Draw a small bitmap image } x = display.width() * 3 / 4 - LOGO_WIDTH / 2; if (val2 == HIGH) { drawbitmap_on(x, y); // Draw a small bitmap image } else { drawbitmap_off(x, y); // Draw a small bitmap image } display.setTextSize(2); // Draw 2X-scale text display.setTextColor(SSD1306_WHITE); display.setCursor(25, display.height() / 2); int speed_int = (int)(val_speed * 3.6 + 0.5); if (speed_int < 100) { display.print(F(" ")); } if (speed_int < 10) { display.print(F(" ")); } display.print(speed_int); display.print(F(" km/h")); display.display(); } void loop() { // put your main code here, to run repeatedly: val1 = digitalRead(digitalPin1); val2 = digitalRead(digitalPin2); need_draw = 0; time0 = millis(); if (time0 - time1 > 15000) { val_speed = 0; time1 = time2 = time0; need_draw = 1; } if (time0 - time2 > 15000) { val_speed = 0; time1 = time2 = time0; need_draw = 1; } if (val1 == HIGH) { curr_flag1 = 1; } else { curr_flag1 = 0; } if (prev_flag1 != curr_flag1) { chng_flag1 = 1; if (curr_flag1 > 0) { time1 = millis(); } } else { chng_flag1 = 0; } if (val2 == HIGH) { curr_flag2 = 1; } else { curr_flag2 = 0; } if (prev_flag2 != curr_flag2) { chng_flag2 = 1; if (curr_flag2 > 0) { time2 = millis(); if (time2 > time1) { float delta_t = time2 - time1; val_speed = 150.0 * 124.0 / delta_t; } } } else { chng_flag2 = 0; } if (chng_flag1 + chng_flag2 + need_draw > 0) { drawflags(); } delay(10); prev_flag1 = curr_flag1; prev_flag2 = curr_flag2; }