ひっそりと「タイトルなし。」を更新しました。
よかったら見てやってください。
SQL ServerのISNULL関数、OracleのNVL関数、MySqlのIFNULL関数。
そして、PostgreSQLのCOALESCE関数。
どれも同じ機能ですが、COALESCEの綴りがすっごく覚えづらいですよね。
なので、私はこう覚えました。
「コーアル・イー・ソニー・コンピュータエンタテインメント *1」
*1 ソニー・インタラクティブエンタテインメントの前の名前。略称が「SCE」。
業務システムのモックを作るとき、ヘッダーとかにユーザー名を表示しますよね。
その時、最大文字数を考慮して
ユーザー名: 勅使河原 権左衛門 [ログアウト]
って仮置きしたら笑われました。
そんなに変ですか(´・ω・`)
いま、野球が好きな友人のために投球スピードを測る装置を作っています。
スピードガンは高いので代わりとなる装置を自作してみていますw
その過程を動画にしていますので、よかったら見ていってください。
んで、そのプログラムのソースコードを以下に掲載します。
疑問点等ありましたら、このブログか動画のコメント欄でご質問いただければ、可能な限り回答いたします。
/*
* psmts01.cpp
*
* Created: 2021/06/03 23:29:02
* Author: piske
*/
// CPU の速度を指定します。
#define F_CPU 16000000UL
// ライブラリをインクルードします。
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay_basic.h>
#include <util/delay.h>
// Arduino の millis() の仕組みから転用 ここから
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
ISR(TIMER0_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
// 転用ここまで
// ビット操作のマクロ定義
#define sbi(PORT,BIT) PORT |= _BV(BIT)
#define cbi(PORT,BIT) PORT &=~_BV(BIT)
// 設定距離の EEPROM アドレス
#define EEPROM_DISTANCE 0x0000
// 押下継続フラグ
#define PRESS_DISTANCE_DOWN 0
#define PRESS_DISTANCE_UP 1
#define PRESS_MEASURE 2
// 関数プロトタイプの定義
void show7Seg(unsigned char digit, unsigned char pattern);
// 7 セグメント点灯パターンの定義
unsigned char segments[] = {0b11110011,
0b01100000,
0b11010101,
0b11110100,
0b01100110,
0b10110110,
0b10110111,
0b11100010,
0b11110111,
0b11110110};
// 7 セグメント点灯パターンの定義 (配線間違えていないバージョン)
//unsigned char segments[] = {0b11111100,
// 0b01100000,
// 0b11011010,
// 0b11110010,
// 0b01100110,
// 0b10110110,
// 0b10111110,
// 0b11100100,
// 0b11111110,
// 0b11110110};
// メイン関数
int main(void)
{
unsigned char distance; // 設定距離
unsigned short speed; // 測定速度
unsigned long pitchTime; // 投球時間
unsigned char pressFlg; // 押下継続フラグ
// ポート方向と内部プルアップを設定します。
DDRB = 0b00111111;
PORTB = 0b11000000;
DDRD = 0b00000000;
PORTD = 0b01000000;
// タイマーの設定をします。
TIMSK = (1<<TOIE0);
TCCR0A = (0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B = (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
sei();
// 設定距離を EEPROM から読み込みます。
eeprom_busy_wait();
distance = eeprom_read_byte(EEPROM_DISTANCE);
// 設定距離が範囲外の場合、初期値を設定します。
if (distance < 1 || distance > 99)
{
distance = 15;
}
// グローバル変数を初期化します。
speed = 0;
pitchTime = 0;
pressFlg = 0;
// メイン ループ
while(1)
{
// 設定距離の桁を分けます。
unsigned char distance2 = distance / 10;
unsigned char distance1 = distance - (distance2 * 10);
// 設定距離を表示します。
show7Seg(0, segments[distance1]);
if (distance2 > 0)
{
show7Seg(1, segments[distance2]);
}
// 測定速度の桁を分けます。
unsigned char speed3 = speed / 100;
unsigned char speed2 = (speed - (speed3 * 100)) / 10;
unsigned char speed1 = speed - (speed2 * 10) - (speed3 * 100);
// 測定速度を表示します。
if (speed1 > 0 || speed2 > 0 || speed3 > 0)
{
show7Seg(2, segments[speed1]); // 手元表示器用
show7Seg(5, ~segments[speed1]); // 主表示器用
}
if (speed2 > 0 || speed3 > 0)
{
show7Seg(3, segments[speed2]); // 手元表示器用
show7Seg(6, ~segments[speed2]); // 主表示器用
}
if (speed3 > 0)
{
show7Seg(4, segments[speed3]); // 手元表示器用
show7Seg(7, ~segments[speed3]); // 主表示器用
}
// 設定距離ダウンを検出します。
if (bit_is_clear(PINB, PB6))
{
// 押下継続でない場合
if (bit_is_clear(pressFlg, PRESS_DISTANCE_DOWN)) {
// 設定距離が 1m より大きい場合、1m ダウンします。
if (distance > 1)
{
distance--;
// 設定距離を EEPROM に保存します。
eeprom_busy_wait();
eeprom_write_byte(EEPROM_DISTANCE, distance);
}
// 押下継続フラグを立てます。
sbi(pressFlg, PRESS_DISTANCE_DOWN);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
}
else
{
// 押下継続フラグを落とします。
cbi(pressFlg, PRESS_DISTANCE_DOWN);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
// 設定距離アップを検出します。
if (bit_is_clear(PINB, PB7))
{
// 押下継続でない場合
if (bit_is_clear(pressFlg, PRESS_DISTANCE_UP)) {
// 設定距離が 99m より小さい場合、1m アップします。
if (distance < 99)
{
distance++;
// 設定距離を EEPROM に保存します。
eeprom_busy_wait();
eeprom_write_byte(EEPROM_DISTANCE, distance);
}
// 押下継続フラグを立てます。
sbi(pressFlg, PRESS_DISTANCE_UP);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
}
else
{
// 押下継続フラグを落とします。
cbi(pressFlg, PRESS_DISTANCE_UP);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
// 測定ボタンを検出します。
if (bit_is_clear(PIND, PD6))
{
// 押下継続でない場合
if (bit_is_clear(pressFlg, PRESS_MEASURE)) {
if (pitchTime == 0)
{
// 測定中でない場合、測定速度をクリアし、投球時間を保持します。
speed = 0;
pitchTime = millis();
}
else
{
// 測定中の場合、現在の時間 (捕球時間) と投球時間の差から測定速度を求めます。
speed = (double) distance * 3600 / (millis() - pitchTime);
// 測定速度が 999km/h を超える場合、999km/h に設定します。
if (speed > 999)
{
speed = 999;
}
// 投球時間に 0 を設定します (測定中でないことを表します)。
pitchTime = 0;
}
// 押下継続フラグを立てます。
sbi(pressFlg, PRESS_MEASURE);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
}
else
{
// 押下継続フラグを落とします。
cbi(pressFlg, PRESS_MEASURE);
// 100マイクロ秒待ちます (チャタリング対策)。
_delay_us(100);
}
}
}
// 7 セグメント表示器に数字を表示します。
void show7Seg(unsigned char digit, unsigned char pattern)
{
unsigned char i;
// シフト レジスタにパターンを送り込みます。
for (i = 0; i < 8; i++)
{
if ((pattern & 1) == 0)
{
sbi(PORTB, PB5);
}
sbi(PORTB, PB4);
cbi(PORTB, PB4);
cbi(PORTB, PB5);
pattern = pattern >> 1;
}
// ライン デコーダに値を設定します。
for (i = 0; i < 3; i++)
{
if ((digit >> i & 1) == 1)
{
sbi(PORTB, PB3 - i);
}
else
{
cbi(PORTB, PB3 - i);
}
}
// ライン デコーダのイネーブルをオンにし、100マイクロ秒待ちます。
sbi(PORTB, PB0);
_delay_us(100);
// ライン デコーダのイネーブルをオフにします。
cbi(PORTB, PB0);
}
男もすなる動画といふものを、女もしてみむとてするなり。
ということでYouTubeに動画をアップしてみました。
応援よろしくお願いします!
自分の日記を読み返してみて、少し恥ずかしくなりました。
5年前の記事で偉そうにに語っていた件です。
「天ぷら」変数の名前を「tempura」と表記するのが正しいと主張していましたが、もっといい例がありました。
「店舗コード」変数
です。
この変数に名前をつけるとき、以下のような揺らぎが発生します。
・tenpo_cd
・tempo_cd
・shop_cd
・store_cd
・tenpo_code
・tempo_code
・shop_code
・store_code
要は、「店舗」を「tenpo」にするのか「tempo」にするのか「shop」にするのか「store」にするのか。
また、「コード」を「cd」にするのか「code」にするのかで上記のパターンが生まれるわけです。
こうなってくると個人の感性の問題としか言いようがないのではないでしょうか。
店舗を「shop」か「store」のどちらかに訳すかなんて、最たる例だと思います。
しかも、「店舗」を「tempo」としてしまうと、「音楽のテンポ」を想起してしまうのが問題となりそうです。
結局は、信頼できるドキュメントを横に置いておいてコピペするのが最強なのではないでしょうかw
昨日以前の記事を読んでいない方はこちらから
朝、正確には覚えていないのですがおそらく7時ごろ。
目覚めたら床で寝ていましたw
どんだけ寝相が悪いんだと自身に呆れ返って苦笑しながらベッドに這い上がり、横になりました。
それから少しして、部屋の電話が鳴り響きました。
時計を見ると10時過ぎを指していました。
少しじゃねえ!
取り敢えず電話に出て、すぐにチェックアウトする旨を伝えました。
延長料金は不要とのことでした。ホテルにはご迷惑をかけてしまいました。
寝坊をしてしまったので、急ぎ仙台に向かいます。
今日の19時30分のフェリーで北海道に帰る予定です。
ちなみに、日焼け対策として手首のサポーターを用意しました。
昨日の朝、青森を出発する前に買っておけばよかったと後悔しております。
お昼まで、特筆することなくひたすら走ります。
酷い山道に案内されたりなどもありませんでした。
ただ、時間の割に進む距離が伸びないことに気づきました。
盛岡までは1km=1分 (60km/h) で計算できていたのが、どうも狂っているようです。
曲がり角などのチェックポイントまでの距離と、その時刻を記憶しながら進んでいくと、どうも平均40km/h計算になるようです。
これは、都会に近づいていることを意味しているのでしょうか。
ややあって、今日のおおよそ中間地点まで来ました。
ここで遅めの昼食を摂ることにします。
今回の旅行の最終目的地は、当初盛岡でした。
盛岡から最終日に八戸まで戻ってフェリーに乗ろうと考えていました。が……
| 八戸発 | → | 苫小牧着 | |
| 8:45 | → | 16:00 | 間に合わない |
| 13:00 | → | 20:15 | 間に合わないこともないが…… |
| 17:30 | → | 翌1:30 | 到着時刻ww |
| 22:00 | → | 翌6:00 | 到着が朝早いな…… |
時刻表が微妙でした。
なので、思い切って仙台まで南下しちゃおうと決めたのです。
ややあって仙台市に入りました。駅方面へ向かう道は初見殺しで、Uターンする羽目になってしまいました。
東北6県のうち宮城県 (仙台市) は別格という話をテレビ等で聞いたことがありましたが、走ってみると建物は高いし、車も多いしで本当なんだな、と実感しました。
ちなみに、仙台行きを決めた理由はもう一つ。マルツ仙台上杉店 (電子部品のお店) があるからですw
そして、フェリーに乗船して今に至ります。
バイクでここまで長距離を一気に走ったのは、今回が初めてとなりました。
現在までのトリップメーターが 680km ほどで、苫小牧→江別が60km ほどと見込んでいるので、700kmを超えることになります。
今回、会社を辞めたことはチャンスとも賭けともいえる状況なのでこの先を楽観視することはできないのですが、時間に余裕ができたことで今回の旅行を遂行することができたことには意義がありました。
今後、小規模ではあるでしょうがツーリングの記事もちょいちょい書いていきたいと思っています。
昨日の記事を読んでいない方はこちらから
2日目の朝になりました。
昨晩なかなか寝付けなかったのですが不思議と眠気はありません。
遠足の前に寝付けないとか小学生かよw
とりあえず、青森駅前の雰囲気を見に行きます。
なんとなく、個人的な主観ですが、北海道に似ているような気がします。
いよいよ南下を始めます。
Google Maps さんの指示では田代平経由で行けとのことですが、国道を逸れても大丈夫かな? とは思いましたが指示に従ってみることにします。
その途中、こんな看板が現れました。
※走行中のため写真が撮れませんでした。そのため、Googleストリートビューより写真を拝借しております。
ふーん、十和田湖通るんだ。時間あったら寄っていこう。
ていうか、括弧の「このろ」ってなんだろう? こっちの方言か何かかな?
なんて思っていたら。
「ねのくち」って、書いてありました。すみませんw
さて。時間があったら十和田湖に寄っていこうなんて言っていたのですが、道の雰囲気がだんだんと怪しくなっていきました。
もしかして、山道に案内された……?
速い車が後ろから来る度に端に寄って抜かさせつつ、なんとかたどり着いた先にあったものが……。
八甲田山じゃねーか!!
その後、なんとかして十和田まで到着しました。
この思いをすると、日勝峠なんか平坦路も同然に感じます。
その後、ひたすら国道4号を進めば良いと思っていたのですが、Google Maps 軍曹は「曲がれ」と指示します。
さすがに身の危険を感じたピースケ新兵がその先のルートを確認すると、単に4号線を迂回した近道を示しているようです。
それに安心して従ってみたのですが、まあまあちょっとした山道でしたw
ちょうど山道に入るときにBluetoothレシーバーの充電が切れて案内音声が聞けず、曲がり角を通り過ぎてしまったため少し遠回りをしながらも、なんとか国道4号に再合流できました。
今日の第一目的地である冷麺のお店には、当初15時ごろに到着する計算でした。
が、目的地を再検索すると「閉店時間が迫ってるけどいいの?」という警告が出ました。
調査不足で、15時から17時までお昼休みだそうでした。
幸い、到着予想時刻は14時半だったので、休憩もそこそこに急ぎ向かいます。
相変わらずの軍曹ぶりを発揮する Google Maps により細い道を通されたりしながらも、予定通りの時間に目的のお店に着きました。
牛ハラミを口に入れた後に冷麺のスープをすすると、こってりとあっさりが中和してなんとも言えないすっきりとした味わいとなりました。
肝心の冷麺ももちもちとした食感がたまらず、程なく完食しました。
予約した時間よりずいぶん早いですが、ホテルに向かうことにしました。
ホテルまでは20分弱で着くことができました。
部屋に着いて荷物をまとめていると、手首に謎の痛みが襲ってきました。
なんだろうとみてみると、日焼けがすごいことになっていました。
薬を買いにツルハに行き、店員さんに「日焼けをしちゃった後の薬ってどれですか?」と聞いて手首を見せたら「何をしたらこんなことになるんですか!?」と言われてしまいましたw
ちなみに、グローブ (手袋) とシャツの袖との間の隙間でこのような日焼けになってしまいます。
その後、盛岡駅周辺を散策しました。
散策後にホテルに戻って少し休憩し、お腹が空いてきたのでご飯を食べに再度外出しました。
場所は「ホテルに近くて美味しそうなお店」という単純な動機で見つけました。
店内は混んでも空いてもおらず、奥には団体さんがいる様子でした。
一人であることを伝えるとカウンター席に通されました。
まずは「これがオススメ!」と言わんばかりに置いてあったメニューの「盛岡りんごハイボール」を注文しました。
りんごの甘味と酸味が程よく、お酒も料理も美味しくいただけました。
また、カウンターならでは、店主さんにオススメを聞いたり、当地の話など聞けたり楽しく会話しつつ食事することができました。
と、旅の思い出を綴りつつ晩酌をするのであります。
Happy birthday to …
Me! (お約束)
HAHAHA…
誕生日と関係ないのですが、この度会社を辞めました。
そこで、時間に余裕ができたのでツーリングでもしてみようかと思いつきました。
9時20分に江別を出発し、中山峠を経由して一路函館を目指します。
途中、前職の残務整理のための電話がかかってきました。
電話が長引いて水を差された気分になりましたが、気を取り直して再出発します。
その後、
| 鳴りまくる、電 | |
| 話 | 第 壱 話 |
休憩のたびに折り返していたような印象です。
時間も押していく一方で、少々焦りました。
次の休憩も電話対応です。
ていうか前職の職場、技術者不在のシステム会社になってしまって……。今後どうするつもりなんだろう?
尻が痛くなってきたので休憩。
この頃になってくると問い合わせは収束してきました。
15時40分、函館に着きました。
当初の予定より40分押してしまいました……。
(うち20分は寝坊のせいです。HAHAHA)
函館を目指してきた理由は、10年ほど前に函館旅行をした際に食べたラーメンをもう一度食べてみたいと思ったからです。
そのラーメン屋さんは五稜郭にある「麺厨房 あじさい」です。
当時、透き通ったスープなのにコクのある味わいに衝撃を受けました。
その数年後、Uターンしてから札幌のら〜めん共和国にあじさいが出店していることがわかり、食べに行きました。
が、当時ほどの衝撃を感じられませんでした。本店じゃないからなのかな、と思い悶々としていたのですが、今日、その本店の味と再会することができます。
肝心のお味は。まずはスープを一口……。
あれ?
決して不味くはないです。ないのですが……。衝撃が足りません。
なんだろう、この感覚……。思い出補正とかでしょうかね……?
さて。当初の予定ではこのまま函館に一泊して、明日、来た道を帰るはずでした。
が、この話には続きができてしまいました。
フェリー、乗っちゃいましたww
思い切って東北周っちゃえ、とw
この先は土地勘の全くない場所。どんな珍道中が待ち受けているのか楽しみです。
4時間程度の乗船時間なので、大部屋でいいかと一番安い運賃で乗りました。
結果、船内はガラガラで大部屋を一人使用するという贅沢な船旅となりましたw

津軽海峡フェリー ブルードルフィン号 自由席 (17:30)
しばらくして青森港に着き、船員さんに「バイクをバックさせたらすぐに降りられますよ」とお声がけいただくという神対応によって、思ったより早く下船することができました。
今日は遅いので、部屋で酒盛りをして営業終了です。






























最近のコメント