その前にネットで調べてみたら、一般向けの商品として、フジ電気工業「リバースコール」といった製品も↓ここで売られていたようです。
すでにこの製品は販売終了しているようですし、1万円はちょっと高いなぁということで自作してみることにしました。
私の場合、ちょうどカーナビ接続キットのKJ-S102DKの取説にバック信号がかいてあったのでナビ裏の線から取出すことにしました。テスターで調べてみると、バック時に+12.6Vが出力されていることがわかりました。今回、ナビ裏からとりましたが、線がわかればバック時の後退灯からとっても良いです。



手元に圧電スピーカー、DCDCコンバーター、PICがあったので、ちょっと回路を作ってテストしてみました。ブレッドボード上で繋げて電源を入れると音がピーピーなるようにしてみます。
使ったPICはPIC10F200というめちゃくちゃ低機能のPICで、初めてPICを触った時にお勉強用に買ったモノでした。+12Vの電源が入るとDCDCコンバーターで5Vを作りPICが動きだし、GP0のOUTピンをオンオフして圧電ブザーを鳴らすという至って単純なものになります。はじめはPICのOUTの5V出力に圧電スピーカーを直でつなぎ鳴らしてみました。
少し音量が小さい気がしたので、トランジスタを使って12Vで鳴らせるようにもしてみました。


最近は無料で基板を作るソフトがあるんですね。KiCadというソフトで作ってみます。最初は理解するのに苦労しましたが、ネットに色々と情報があるので先人の知恵を借りて作成してみます。ReveP(リバピー)ってシルクも入れてみました。
KiCadで作ってみたのがこれ↑。
そして、実際にネット基板作成サービスにデータを出して作ってもらい、来たのがこれ↓ちょっと感動です。

1枚で良かったのですが、15枚もできちゃいました・・・。(フリマにでも出すか?いや売れるのか?)
基板の中心の圧電スピーカーを5Vで鳴らすか12Vで鳴らすかは、2本の足を縦に挿すか横に挿すかで変わります。


部品をハンダして、3Dプリンタで入れるケースも作ってみました。切り欠きはタイラップを巻くときの溝になります。
]]>といいますのも、1歳の娘用にアマゾンで格安のポータブルDVDプレイヤーを購入したのですが、DVDの再生以外に、USBメモリやSDでXvidの動画ファイルも再生できるようなことが書いてあったので、挑戦してみたのが今回のXvid作成の背景になります。

で、普通になにも考えずにAvitlでXvid動画を作成し、DVDプレイヤーで再生ができるところまではもっていけたのですが、長い動画を再生していると音声が徐々にずれていき、20分ぐらいの動画の後半では3秒くらい音ズレてしまいました。音声が先行し、映像が遅れている感じです。その症状を解消するための方法を解説していきます。
まずは、まえもって用意するものは以下になります
①変換元の動画ファイル(mp4など)
②Aviutl
③Aviutl入力プラグイン:L-SMASH Works (mp4読込用)
④Xvid(動画エンコード用コーデック)
⑤LameACM(音声エンコード用コーデック)
①の変換元の動画ファイルは何でもよいので用意してください
②のAviutlはAviutlの公式サイトからVer1.10を落としてきます
③のL-SMASH WorksはMr-Ojii版とRePOPn版がありますが、どちらでも良いのでAviutlのプラグインに入れておきましょう。私はMr-Ojii版を入れました。
④はXvidは公式サイトからダウンロードしてインストールします。
⑤LameACMはバージョン3.99.5 ACM codecをダウンロードしてインストールします。インストールはOSが32bitと64bitでやり方が違うようです。32bitはinfを右クリックでインストール。64bitは管理者権限のコマンドプロンプトでコマンドを実行してインストールします。丁寧に解説しているサイトがあるのでググってください。
ここまでで準備ができました。次のページから実際のやり方を説明します。

STLファイルで保存して3Dプリンタで印刷。待つこと1時間30分…。

完成しました!


参考に、実際に印刷したSTLファイルをアップロードしておきます。
3Dプリンタ
]]>単純なサンプルを載せておきます。
/*
* 単純にProxy経由でWEBページを取得するサンプル
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
void setup() {
Serial.begin(115200);
Serial.println();
WiFi.mode(WIFI_STA);
WiFi.begin("SSID", "PASSWORD");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// wait for WiFi connection
if((WiFi.status() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTP] begin...\n");
//Proxyサーバを使う場合
http.begin("Proxy.server.ip",8080,"http://www.dmsk.com/pc/main-hw.html");
//Proxyサーバを使わない場合
//http.begin("http://www.dmsk.com/pc/main-hw.html");
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if(httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
delay(20000);
}
解説というほどのこともないですが、
35行目で、Proxyサーバのアドレス、ポート、開きたいページのURLを指定するだけです。
天気予報はYahooやLivedoorが無料でRSSを提供してくれています。他にもgooとかもやってみたいです。今回はYahoo!の天気予報をマイコンで表示したりするのに利用しやすくするためにごにょごにょしたことをまとめておきたいと思います。
まず、Yahooの天気予報のRSSは、次のページで各地域ごとにxml形式で提供されています。
https://weather.yahoo.co.jp/weather/rss/
実際に開いてみるとわかりますが、更新日時とか、警報や注意報など天気以外の表示するのに必要なさそうな情報も沢山入っています。この大量の文字列からパターンマッチをして必要な文字列を切り出して来なければなりません。なんて考えていたらマイコンでこの処理をさせるのは大変だーと思ってきました。さらに、Yahooの天気予報はhttpsなのでセキュア通信もさせなくてはなりません…。うーん、httpsだとプロキシ経由だったりするとページを取得するだけでも難しそうだな、、、などなど色々考えた結果。扱いやすいデータに変換してからマイコンで受信したほうが簡単じゃないか(?)というとこに至ったのでした。
前置きが長くなりましたが、今回やってみるのは、PHPを使ってマイコンで使いやすい天気予報データに変換しちゃおう♪というのが狙いです。
概要:
・Yahooの天気予報のRSSを利用
・WEBサーバ上で動くPHPプログラムを作成してみる
(PHPにした理由はPHPだと簡単だから)
■getytenki.phpのプログラム
<?php
header('Content-type: application/xml; charset=UTF-8');
date_default_timezone_set('Asia/Tokyo');
//リクエストURLから数字文字列を取得
$placeNo = htmlspecialchars($_GET["p"]);
//Yahoo天気のxmlファイルのURL
$xmlurl = "https://rss-weather.yahoo.co.jp/rss/days/" . $placeNo . ".xml";
//xml読み込む
$lines = file($xmlurl);
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
echo "<root>\n";
echo "<sourceurl>" . $xmlurl . "</sourceurl>\n";
echo "<dataprovider>Yahoo!天気・災害</dataprovider>\n";
foreach ($lines as $line_num => $line) {
//copyright表示
if(preg_match('/<copyright(.+)copyright>/',$line,$matches)){
echo $matches[0] . "\n";
echo "<today>" . date('Y年m月d日') . "</today>\n";
}
//<title>タグの情報を読み込む
if(preg_match_all('/<title>(.+?)<\/title>/',$line,$matches)){
//print_r($matches);
//場所の文字列を抜き出す
if(preg_match('/災害 - (.+)の天気/',$matches[1][0],$place)){
echo "<place>" . mb_convert_kana($place[1],'a','UTF-8') . "</place>\n"; //全角→半角にもしておく
}
//天気情報を抜き出す
foreach ($matches[1] as $mt_num => $mt) {
if(preg_match_all('/【 (.+日.+?)).+ 】 (.+) - (.+) - /',$mt,$dt)){
//print_r($dt);
echo "<item>";
echo mb_convert_kana($dt[1][0],'a','UTF-8') . ":" . $dt[2][0] . ":" . $dt[3][0];
echo "</item>\n";
}
}
}
}
echo "</root>\n";
プログラムはたったこれだけです。
上記プログラムをPHPが動くWEBサーバに置いてアクセスしてみます。ゆくゆくはマイコンでアクセスさせますが、まずはパソコンで確認です。
http://bmicom.dmsk.com/php/getytenki.php?p=4820
URLのおしりの数字は、Yahooの天気予報のxmlファイル名の数字です。ブラウザによっては文字が羅列されているかもしれませんが、ソースを見てもらうとxml形式になっているのがわかります。
今回は4820なので長野県松本の天気情報が取得できました。
出力されるxmlの文字コードはUTF-8になっています。
もしかしたらフォントの関係とかでShift-JISで受信したい場合もあるかもしれません。そんなときは以下のようにして、PHP側でShift-JISにしてしまうのも手かと思います。
■getytenkisj.phpのプログラム
<?php
header('Content-type: application/xml; charset=Shift_JIS');
date_default_timezone_set('Asia/Tokyo');
//リクエストURLから数字文字列を取得
$placeNo = htmlspecialchars($_GET["p"]);
//Yahoo天気のxmlファイルのURL
$xmlurl = "https://rss-weather.yahoo.co.jp/rss/days/" . $placeNo . ".xml";
//xml読み込む
$lines = file($xmlurl);
echo mb_convert_encoding("<?xml version=\"1.0\" encoding=\"Shift-JIS\"?>\n", "SJIS", "UTF-8");
echo mb_convert_encoding("<root>\n", "SJIS", "UTF-8");
echo mb_convert_encoding("<sourceurl>" . $xmlurl . "</sourceurl>\n", "SJIS", "UTF-8");
echo mb_convert_encoding("<dataprovider>Yahoo!天気・災害</dataprovider>\n", "SJIS", "UTF-8");
foreach ($lines as $line_num => $line) {
//copyright表示
if(preg_match('/<copyright(.+)copyright>/',$line,$matches)){
echo mb_convert_encoding($matches[0] . "\n", "SJIS", "UTF-8");
echo mb_convert_encoding("<today>" . date('Y年m月d日') . "</today>\n", "SJIS", "UTF-8");
}
//<title>タグの情報を読み込む
if(preg_match_all('/<title>(.+?)<\/title>/',$line,$matches)){
//print_r($matches);
//場所の文字列を抜き出す
if(preg_match('/災害 - (.+)の天気/',$matches[1][0],$place)){
echo mb_convert_encoding("<place>" . mb_convert_kana($place[1],'a','UTF-8') . "</place>\n", "SJIS", "UTF-8"); //全角→半角にもしておく
}
//天気情報を抜き出す
foreach ($matches[1] as $mt_num => $mt) {
if(preg_match_all('/【 (.+日.+?)).+ 】 (.+) - (.+) - /',$mt,$dt)){
//print_r($dt);
echo mb_convert_encoding("<item>", "SJIS", "UTF-8");
echo mb_convert_encoding(mb_convert_kana($dt[1][0],'a','UTF-8') . ":" . $dt[2][0] . ":" . $dt[3][0], "SJIS", "UTF-8");
echo mb_convert_encoding("</item>\n", "SJIS", "UTF-8");
}
}
}
}
echo "</root>\n";
]]>
概要:
・Arduinoの開発環境でプログラミングしてESP-WROOM-02に書込む
・サーバ側はSoftAPモードでWiFiアクセスポイントを開設
・クライアント側はSWを押すとコマンドをサーバに送る
・サーバ側は送られて来たコマンドを見てLEDをON/OFFする
動作イメージ
クライアント側のSWを押すとサーバ側のLEDが光ります
//サーバ側プログラム
#include <ESP8266WiFi.h>
static const char *SSID = "WROOM-B'MICOM";
static const char *PASSWD = "password";
const int LED1 = 12; //SW1のIOピン
const int LED2 = 16; //SW2のIOピン
const int LED3 = 5; //SW3のIOピン
const int LED4 = 4; //SW4のIOピン
IPAddress ip(192, 168, 0, 33);
//IPAddress gateway(192, 168, 0, 1);
//IPAddress netmask(255, 255, 255, 0);
WiFiServer server(26842); //Port番号
void setup() {
Serial.begin(115200);
Serial.println();
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
//起動時LEDを光らせてみる
digitalWrite(LED1, HIGH);
delay(100);
digitalWrite(LED1, LOW);
digitalWrite(LED2, HIGH);
delay(100);
digitalWrite(LED2, LOW);
digitalWrite(LED3, HIGH);
delay(100);
digitalWrite(LED3, LOW);
digitalWrite(LED4, HIGH);
delay(100);
digitalWrite(LED4, LOW);
//WiFiアクセスポイントを開始
WiFi.mode(WIFI_AP);
WiFi.softAP(SSID, PASSWD);
WiFi.softAPConfig(ip, WiFi.gatewayIP(), WiFi.subnetMask());
//WiFi.softAPConfig(ip, gateway, netmask);
WiFi.begin();
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP Started. myIP address: ");
Serial.println(myIP);
//Portのlistenを開始
server.begin();
Serial.println("Server started");
}
void loop() {
String cmd;
cmd = rcvCommand();
//受信したコマンドに対応したLEDを点灯/消灯
if(cmd == "LED1OFF"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED1, LOW);
}
if(cmd == "LED1ON"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED1, HIGH);
}
if(cmd == "LED2OFF"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED2, LOW);
}
if(cmd == "LED2ON"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED2, HIGH);
}
if(cmd == "LED3OFF"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED3, LOW);
}
if(cmd == "LED3ON"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED3, HIGH);
}
if(cmd == "LED4OFF"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED4, LOW);
}
if(cmd == "LED4ON"){
Serial.print("Exec: ");
Serial.println(cmd);
digitalWrite(LED4, HIGH);
}
}
//コマンドを受信してそのコマンド文字列を返す
String rcvCommand(){
WiFiClient client = server.available();
String rstr;
if (client.connected()) {
Serial.println("Connected to client");
//コマンド文字列受信(文字列が来なければタイムアウトする)
rstr = client.readStringUntil('\r');
Serial.print("[");
Serial.print(rstr);
Serial.println("]");
//応答送信
client.print("OK\r");
//接続をクローズ
client.stop();
Serial.println("Closed");
}
return rstr;
}
//クライアント側プログラム
#include <ESP8266WiFi.h>
#include <Ticker.h>
#define SW_ONDELAY 4000 //SWチャタリング防止ディレイ(ループカウント数)
#define SW_OFFDELAY 4000 //SWチャタリング防止ディレイ(ループカウント数)
Ticker ticker1; //タイマ割り込み (LED点滅用)
const char* ssid = "WROOM-B'MICOM";
const char* password = "password";
char hostIP[] = "192.168.0.33";
int hostPort = 26842;
const int SW1 = 12; //SW1のIOピン
const int SW2 = 16; //SW2のIOピン
const int SW3 = 5; //SW3のIOピン
const int SW4 = 4; //SW4のIOピン
const int LED = 13; //LEDのIOピン
int ledStatus = 0; //0:消灯 1:点灯 2:点滅
int sw1Status = 0; //0:OFF 1:ON
int sw2Status = 0; //0:OFF 1:ON
int sw3Status = 0; //0:OFF 1:ON
int sw4Status = 0; //0:OFF 1:ON
WiFiClient client;
void setup() {
Serial.begin(115200);
//タイマ割り込み間隔と 割り込み関数名 LEDの点滅に使用
ticker1.attach_ms(500, ticker1_interrupt);
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
pinMode(SW3, INPUT);
pinMode(SW4, INPUT);
pinMode(LED, OUTPUT);
Serial.println("Booting...");
WiFi.mode(WIFI_STA);
connectToWiFi();
}
void connectToWiFi(){
ledStatus = 2;//0:消灯 1:点灯 2:点滅
WiFi.begin(ssid, password);
delay(500);
int retrycnt = 0;
while(WiFi.waitForConnectResult() != WL_CONNECTED){
Serial.print(".");
delay(100);
retrycnt++;
if(retrycnt > 100){
ESP.restart();
}
}
Serial.println("Connect Success");
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
ledStatus = 1;//0:消灯 1:点灯 2:点滅
sw1process();
sw2process();
sw3process();
sw4process();
}else{
//WiFi接続が切れた
Serial.println("WiFi ERR. Restart.");
ESP.restart();
}
}
void sendSocket(String str)
{
if (client.connect(hostIP, hostPort))
{
Serial.print("Connected:");
Serial.println(hostIP);
Serial.println("Posting: " + str);
//送信
client.print(str);
//応答受信
client.setTimeout(1000);
do{
String line = client.readStringUntil('\r');
Serial.print(line);
} while (client.available() != 0); //残りがあるときはさらに受信のためループ
Serial.println();
}
else
{
Serial.println("Connection failed.");
}
}
//SW1の処理
int sw1onCnt = 0;
int sw1offCnt = 0;
void sw1process(){
if(sw1Status == 0){
if(digitalRead(SW1) == HIGH){
sw1onCnt++;
if(sw1onCnt == SW_ONDELAY){
//ON送信
sendSocket("LED1ON\r");;
sw1Status = 1;
sw1offCnt = 0;
}else if(sw1onCnt > SW_ONDELAY){
sw1onCnt = SW_ONDELAY;
}
}else{
sw1onCnt = 0;
}
}else{
if(digitalRead(SW1) == LOW){
sw1offCnt++;
if(sw1offCnt == SW_OFFDELAY){
//OFF送信
sendSocket("LED1OFF\r");
sw1Status = 0;
sw1onCnt = 0;
}else if(sw1offCnt > SW_OFFDELAY){
sw1offCnt = SW_OFFDELAY;
}
}else{
sw1offCnt = 0;
}
}
}
//SW2の処理
int sw2onCnt = 0;
int sw2offCnt = 0;
void sw2process(){
if(sw2Status == 0){
if(digitalRead(SW2) == HIGH){
sw2onCnt++;
if(sw2onCnt == SW_ONDELAY){
//ON送信
sendSocket("LED2ON\r");;
sw2Status = 1;
sw2offCnt = 0;
}else if(sw2onCnt > SW_ONDELAY){
sw2onCnt = SW_ONDELAY;
}
}else{
sw2onCnt = 0;
}
}else{
if(digitalRead(SW2) == LOW){
sw2offCnt++;
if(sw2offCnt == SW_OFFDELAY){
//OFF送信
sendSocket("LED2OFF\r");
sw2Status = 0;
sw2onCnt = 0;
}else if(sw2offCnt > SW_OFFDELAY){
sw2offCnt = SW_OFFDELAY;
}
}else{
sw2offCnt = 0;
}
}
}
//SW3の処理
int sw3onCnt = 0;
int sw3offCnt = 0;
void sw3process(){
if(sw3Status == 0){
if(digitalRead(SW3) == HIGH){
sw3onCnt++;
if(sw3onCnt == SW_ONDELAY){
//ON送信
sendSocket("LED3ON\r");;
sw3Status = 1;
sw3offCnt = 0;
}else if(sw3onCnt > SW_ONDELAY){
sw3onCnt = SW_ONDELAY;
}
}else{
sw3onCnt = 0;
}
}else{
if(digitalRead(SW3) == LOW){
sw3offCnt++;
if(sw3offCnt == SW_OFFDELAY){
//OFF送信
sendSocket("LED3OFF\r");
sw3Status = 0;
sw3onCnt = 0;
}else if(sw3offCnt > SW_OFFDELAY){
sw3offCnt = SW_OFFDELAY;
}
}else{
sw3offCnt = 0;
}
}
}
//SW4の処理
int sw4onCnt = 0;
int sw4offCnt = 0;
void sw4process(){
if(sw4Status == 0){
if(digitalRead(SW4) == HIGH){
sw4onCnt++;
if(sw4onCnt == SW_ONDELAY){
//ON送信
sendSocket("LED4ON\r");;
sw4Status = 1;
sw4offCnt = 0;
}else if(sw4onCnt > SW_ONDELAY){
sw4onCnt = SW_ONDELAY;
}
}else{
sw4onCnt = 0;
}
}else{
if(digitalRead(SW4) == LOW){
sw4offCnt++;
if(sw4offCnt == SW_OFFDELAY){
//OFF送信
sendSocket("LED4OFF\r");
sw4Status = 0;
sw4onCnt = 0;
}else if(sw4offCnt > SW_OFFDELAY){
sw4offCnt = SW_OFFDELAY;
}
}else{
sw4offCnt = 0;
}
}
}
//タイマ割り込み時の処理
void ticker1_interrupt(){
if(ledStatus == 0){
digitalWrite(LED, LOW);
}else if(ledStatus == 1){
digitalWrite(LED, HIGH);
}else if(ledStatus == 2){
digitalWrite(LED, !digitalRead(LED));
}
}
]]>ソレノイドって何?
↑こんなやつです。
ソレノイドとは、電気を流すと中の棒が動く電磁石を利用した電気部品で、これを使って電気をオン・オフして中の棒を動かし、それでボタンを連打しようという魂胆。
実際に私が買ったソレノイドはアマゾンで317円。安い!
とりあえず、動画にしてみたので、ここに貼っておきます。ソレノイドの動きがどんなもんかわかるかと。。。
電気のオン・オフを自動でやらせたいので、こちらもアマゾンで格安で手に入るArduino Nano互換品を使用します。
↑こんな感じのです。これもアマゾンで400円前後!
では実際に回路を考えてみます。
考えてみました…。
上記回路図のコメント
・電源はACアダプタでとる
・ソレノイドの定格が12V1Aなのでそれ相当のACアダプタを用意
(こっそり言うと、そんなACアダプタないよって人は昔の重いトランスタイプのACアダプタなら表示以上の電流が出たりするのでそういうのを使うのも手かもです)
・回路図ではトランジスタを使っていますが、FETやフォトカプラのほうが良いかもしれません。今回は、とりあえずそこらへんにあって使えそうなものを採用しました。
実際に部品を用意して基板にハンダしてみました。
続いてArduinoのプログラムを書いて行きます。
Arduinoの開発環境は公式ページから無料でダウンロードできますし、ブラウザ上で開発するWEB EDITORもあります。
詳しくは、解説しているサイトが沢山あるのでググりましょう(๑´ڡ`๑)テヘペロ
それでは実際にArduino Nano(互換品)に書込んで見ます。以下のプログラムをArduino IDEにコピペしてコンパイル、書き込みをしてみてください。
//ソレノイド連射Arduino Nanoプログラム
int statusmode = 0; //0:連射OFF 1:連射ON
int swcount=0; //SWのチャタリング防止用カウンタ
void setup() {
// シリアルポートを9600bpsで初期化
Serial.begin(9600);
pinMode(2, OUTPUT); //ソレノイドへ出力
pinMode(12, INPUT); //SW入力
pinMode(13, OUTPUT); //LED出力
}
void loop() {
int val ;
int inputchar;
//プッシュSW入力処理
//プッシュSW入力トグルで切替え(連射中/停止中)
if(digitalRead(12)==HIGH){
swcount++;
}else{
swcount=0;
}
if(swcount>100){
swcount=0;
if(statusmode==0){
statusmode=1;
}else if(statusmode==1){
statusmode=0;
}
}
//SW入力以外にもパソコンから
//USBシリアル通信で's'で連射開始、'f'で連射停止も可能
inputchar = Serial.read();
switch(inputchar){
case 's'://start
statusmode = 1;
break;
case 'f'://finish
statusmode = 0;
break;
}
// 半固定抵抗からの読込み値(連射の速度をアナログで変更)
val = analogRead(0) ;
//ソレノイドのオン・オフ処理
if(statusmode == 0){
digitalWrite(13,LOW);
}else if(statusmode == 1){
digitalWrite(13,HIGH);
digitalWrite(2, HIGH);
delay(100);
digitalWrite(13,LOW);
digitalWrite(2, LOW);
delay(val);
}
}
]]>
基板はネジなどで固定せずにコードフックのアームを90度くらいに開いて、そこに乗せるようにしました。こちらのコードフックも100円ショップで購入です。サイズはいろいろあるけど、この写真のは16個入りの極小タイプ。
スポンジのクッションが付いているので大丈夫だとは思いますが、コードフックのベースになっている部分は金属なのでショートしないようになにか巻いておいたほうが安全かもしれません。
]]>
PICマイコンとESP-WROOM-02で電波時計ならぬ、インターネットへ接続しNTPサーバから時刻を取得し自動で時刻修正する時計を作っていきたいと思います。早い話、電波時計のインターネット版だと思ってください。
夏休みの自由研究なんかにうってつけなんじゃないでしょうか?
概要:
・PICはPIC18F25K22-I/SPを使用
・ESP-WROOM-02は公式のNONOSファーム v1.5.4を使用
・プログラムを作って書込むのはPICだけ
・PICとWROOMの通信はUSARTでATコマンドを使用
・7セグをダイナミック点灯。7セグは秋月の[OSL40391-LG]を使用
・時計用のクロックは32.768kHz水晶発振子を使用
・1日に1回時刻を自動修正
・開発環境はMPLAB X v3.30, xc8 v1.3.7を使用
回路は以下の通り。
LED用の抵抗値は使用するLEDに合わせて適宜変えてください。
MPLAB X用プロジェクトファイル
ダウンロード:PIC18F25k22_WifiClock160622a.zip
このプログラムの改変は自由に行ってもらっても良いですが、再配布や直リンクは禁止とします。また、営利目的のための使用も禁止します。
このサイトへのリンクは歓迎です。
使い方:
①まずは、プログラムをご自分のWifi環境に書き換えてください。
変更する箇所はmain.cの冒頭のここの部分。
書換えたらビルドしてPICに書込んでください。
②初回起動時はSW1またはSW2を押したまま電源を投入するとWifiアクセスポイントへ接続をここみます。LEDが点灯したらSWを離してください。
2回目以降の起動はSWを押しながらでなくても最後に接続したアクセスポイントをWROOMは覚えているので自動で接続します。
(Wifiアクセスポイントの設定は2つ登録でき、SW1を押しながらのときとSW2を押しながらのときで切り替えることが可能)
③LEDが点滅になると時刻を調整している最中です(約1分)。
④約1分後、LEDが消灯すれば調整は成功。LEDが点灯だと失敗です。
通常時のスイッチ操作について
SW1を押すと押している間、時刻表示から秒表示に切り替わります。
時刻表示中にSW2を押すと時刻を1分進めます。長く押すとどんどん進めます。
秒表示中にSW2を押すと現在の時刻のまま秒だけ0秒にします。
では、最新版をダウンロードします。
(ファームは日々更新されています。さらに新しいバージョンが出ていたら適宜読み替えて行ってください)
●ファームウェアのデータ本体のダウンロード先は
http://www.espressif.com/en/support/download/sdks-demos
2016/06/12現在最新のESP8266 NONOS SDK V1.5.4をダウンロードしました。
ちなみにATコマンド対応のファームはNONOSというやつです。
最新版のリリースなどいろいろとフォーラム内でアナウンスされているので、詳しく知りたい人はそちらで確認してください。→ESPRESSIFのフォーラム
●書込みツール「ESP8266 Flash Download Tools v2.4」のダウンロードはココ
http://www.espressif.com/en/support/download/other-tools
追記:リンク先のサイトが更新されました。「ESP8266 Flash Download Tools v3.3.4」がリリースされたようですが、まだ試していません。
●資料のpdf「ESP8266 AT Instruction Set」もダウンロードしておきましょう
http://www.espressif.com/en/support/download/documents
↑下線の補足にあるようにダウンロードしたファームウェアバージョンに対応したpdf資料
●回路の修正「IO0をグランドに」
ファームウェアを書き換えるにはIO0をグランド側につなげてあげる必要があります。
パソコン側の接続方法の詳細は前にやったここを参考にしてください。

それではダウンロードした書込みツールを起動します。
V2.4をダウンロードしたはずなのにタイトルバーがV2.3になっているのはご愛敬ですね^^;
一番上の5つのファイルはファームウェア本体を解凍したbinフォルダ内にあります。書込み先アドレスについてはダウンロードしたpdf資料に書いてあります。今回はpdfの6ページ~7ページに書いてある「32Mbit Flash, map:1024KB+1024KB」を使いました。
FLASH SIZEもpdf内で指定されたものを選択します。COMポート番号とボーレートの選択もお忘れなく。最後にSTARTボタンで書込み開始させます。
無事ファームウェアの更新が完了したら、IO0を元のように3.3V側に直して前回同様「AT+GMRコマンド」でもう一度ファームのバージョンを確認してみましょう。
バージョン情報が新しく更新されていれば成功です。