Vol.923 25.Jul.2025

自転車用フラッシャー PICを3.3Vで使う

C 自転車用フラッシャー(方向指示器)

by fjk

・自転車走行中に方向を変える場合、手信号(ハンドサイン)を使っていますか?
・片手運転になるので、合図をせずに曲がってしまうことがありませんか?
・合図不履行で青切符を切られ、3,000円の罰金を取られかねません(片手運転も罰金?)。
 
 こんな時に便利なのが、「自転車用フラッシャー」です。少なくとも後方には合図を送れます。しかし、自転車フラッシャーが法令上の「合図」として認められるかは、よくわからないようです。でも、あった方が良さそうですね(前方にも必要かな?)。
 そこで、Amazonのプライムデーに「自転車 テールライト LED+自転車用方向指示器 LY-6700」(@2,000、本体:USB充電式、簡易防水、手元リモコン付)を購入した。
 なお、LY-6700は本体をゴムバンドでシートポストに取り付けるタイプだが、取付予定の自転車のポスト部に取付けスペースが無かったので、自転車後部に「19x19直交クランプ」と「19φL150のパイプ」を取り付けた。なお、クランプの取付時にスペーサとして「カットした19φの樹脂ホース」も準備した。
 フラッシャーを点灯させれば、両手で運転できるので便利です。左右フラッシャーは90秒後には自動で消灯します。充電時間は1〜2時間。動作時間は4〜6時間とあります。
 難点は日本語マニュアルが無いのと、リモコンのLEDが明るくないので晴天時にはチョット見づらいことかな。


LY-6700(本体、リモコン、取付パーツ等)

取付用に別途準備したモノ

取付前の自転車

 

リモコン・パイプ取付

点灯テスト(左右同時点滅も可)


P PICミニBBシリーズ(23)  〜USB接続でPICを3.3Vで使う

by fjk

 今まで、PICはUSB接続5V動作で、3.3V信号が必要なときは、信号レベル変換デバイスを使っていたが、レベル変換デバイスによっては動作が不安定になることがあった。特に、SPI接続デバイスは3.3V動作の物が多いので、PICを3.3Vで動作させると、レベル変換デバイスが不要となる。
 USB接続ユニットのシリアル信号には3.3Vと5Vのモノがあり、2種類のユニットをテストした。また、USBユニットから3.3V電源が供給できるものもあるが、拡張性を考慮すると別途3.3Vの電源が必要。もし、USBバスパワー+三端子レギュレータを利用する場合、USBユニットから5Vも取り出せること。

【ハード】

@ 3.3V出力シリアルのUSBユニット [#番号は秋月電子]

 ・USBシリアル変換モジュール:
MPL2303SA(マルツ、@894)
5,6,8番端子にはピンを取付けない
 ・三端子レギュレータ:
NJU7223DL1(3.3V/500mA、#103705、@180)
端子並びに注意!(GNDが中央で無い)

回路図
 

BB配線状況

BB配線完了

A 5V出力シリアルのUSBユニット [#番号は秋月電子]

 ・USBシリアル変換モジュール:
FT234X(#108461、@780)
 ・三端子レギュレータ:
NJM2845DL1-33(3.3V/800mA、#111299、@50)

回路図
 

BB配線状況

BB配線完了

【ソフト】 @もAも同じ
・MCCの設定


system module (INTOSCで16MHz)
 

EUSART (115200bps)
 

TMR0 (約1秒毎の割り込みでLED点滅)
 

【abc923-1823/25.c】 abc923-1825.c (zip) [1823.cも同じ]


/*****************************(abc923-1823/25.c)****
 *   PIC Test (3.3V Power)
 ****************************************************/

#include "mcc_generated_files/mcc.h"
#include "myProject.h"

//--- タイマー・汎用変数
char     Msg[20];                           // コメント等送信用文字列
uint8_t  TFlg;                              // タイマーフラグ

//---- EUSART用変数
char     RBuf[EU_BFSIZE];                   // シリアル受信バッファー
uint8_t  SFlg;                              // シリアル受信フラグ

/***************************************
 *  タイマ0 Callback関数 (1秒周期割り込み)
 ***************************************/
void TMR0_Process(void){
    TFlg = 1;                               // タイマーフラグセット
}

/***************************************
 *         Main application
 ***************************************/
void main(void){
    char    cmd;

    SYSTEM_Initialize();

    // タイマ0 Callback関数定義
    TMR0_SetInterruptHandler(TMR0_Process);
    
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    EU_Puts("--- test ---");
    LED_SetHigh();
    
    while (1) {
       // 1秒周期の処理
            if(TFlg){                       // フラグオンの場合
            LED_Toggle();
            TFlg = 0;                       // フラグリセット
        }
       // コマンド処理
        if(SFlg){                           // 受信ありの場合
            cmd = RBuf[0];  
            EU_Write("Input = ");
            EU_Puts(RBuf); 
        
            SFlg = 0;
        }
    }
}
/***   End of File  ***/

・シリアル通信用(mcc_generated_files/eusart.cに2行を追加) 【eusart.c】


/*****  (mcc_generated_files/eusart.c )****
 * 	シリアル通信 (赤字の部分を追加)
 *********************************************/

#include "eusart.h"
#include "../myProject.h"

・・・・<途中省略>・・・・


void EUSART_Receive_ISR(void)
{
    
    eusartRxStatusBuffer[eusartRxHead].status = 0;

    if(RCSTAbits.FERR){
        eusartRxStatusBuffer[eusartRxHead].ferr = 1;
        EUSART_FramingErrorHandler();
    }
    if(RCSTAbits.OERR){
        eusartRxStatusBuffer[eusartRxHead].oerr = 1;
        EUSART_OverrunErrorHandler();
    }
    if(eusartRxStatusBuffer[eusartRxHead].status){
        EUSART_ErrorHandler();
    } else {
        EUSART_RxDataHandler();
    }
    // or set custom function using EUSART_SetRxInterruptHandler()
    myEusart();
}

・・・<以後省略>・・・

・オリジナルライブラリー  【myFunction.c】 myFunction.c + myProject.h(zip)


********************(myFunction.c)******
 *  自作汎用関数
 ****************************************/

#include 
#include "myProject.h"                      // #define EU_BFSIZE

/***  EUSARTシリアル関数用 ********************/

extern char    RBuf[];                      // 受信文字Buffer
extern uint8_t SFlg;                        // 受信フラグ
static uint8_t sIdx = 0;                    // 受信文字列Index

/*--- Eusart受信割り込みハンドラー -------------
 *    eusrt.cのEUSART_Recive_ISRに追加すること
 *---------------------------------------------*/
void myEusart(){
    char ch;
    ch = EUSART_Read();
    #if ECHO == ON
        EUSART_Write(ch);
    #endif
    if((ch == 0x0a)||(ch == 0x0d)){         // 改行処理
        RBuf[sIdx] = 0;
        sIdx = 0;
        SFlg = 1;
    }else if((ch == 0x08)&&(sIdx > 0)){     // BS処理
        sIdx--;
    }else{
        if(sIdx < EU_BFSIZE) RBuf[sIdx++] = ch;
    }
}

/*--- Eusart受信データを返す--------------------
 *    *str:受信データを格納する文字列
 *  RETURN:受信した文字数([0]ならデータ無し)
 *---------------------------------------------*/
/*uint8_t EU_gets(char *str){
    strcpy(str,rBuf);
    return strlen(rBuf);
}
*/
/*--- Eusartへ文字列を送信 ---------------------
 *   *str:送信したい文字列データ
 *---------------------------------------------*/
void EU_Write(char *str){
    while(*str != 0){                       // 文字列終りまで
        EUSART_Write(*str++);               // 1文字送信
    }
}

/*--- Eusartへ改行を送信 ----------------------*/
void EU_Write_CR(void){
    EUSART_Write('\n');
}

/*--- Eusartへ文字列送信(改行付)--------------
 *   *str:送信したい文字列データ
 *---------------------------------------------*/
 void EU_Puts(char *str){
    EU_Write(str);
    EU_Write_CR();
}

/***  文字列変換関数  **************************/
/*---- 16進文字列を10進数に変換[=xtoi()/C90]----
 *    *str:10進数に変化したい16進数文字列
 *  RETURN:変換された32ビット符号無し整数
 *---------------------------------------------*/
uint32_t my_xtol(char *str){
    uint32_t dec;
    dec = strtoul(str,NULL,16);
    return (uint32_t)dec;
}

/*--- 下位4ビットを16進数文字に変換 ------------
 *    n:符号無し16bit整数(最下位の4bitのみ有効)   
 *  RETURN:16進数に対応するアスキー文字
 *---------------------------------------------*/
uint8_t my_utoa2(uint16_t n){
    n &= 0x0F;
    if(n < 10)  return '0'+ (uint8_t)n;
    else        return 'A'+ ((uint8_t)n - 10);
}

/*--- 1ワード(16ビット)を16進文字に変換 -------
 *   *str:変換結果を格納する文字列
 *    wd :変換したい符号無し16ビットデータ
 *    dg :16進数文字列の桁数
 *----------------------------------------------*/
void my_utoa(char *str, uint16_t wd, uint8_t dg){
    if(dg > 3)  *str++ = my_utoa2(wd >> 12);
    if(dg > 2)  *str++ = my_utoa2(wd >> 8);
    if(dg > 1)  *str++ = my_utoa2(wd >> 4);
    *str++ = my_utoa2(wd);
    *str = '\0';
}

/*---  文字列を逆順に入替 -----------------------
 *   *str:文字順を入れ替えたい文字列
 *-----------------------------------------------*/
void reverseString(char *str) {
    uint8_t i, length;
    length = (uint8_t)strlen(str);
    for (int i = 0; i < length / 2; i++) {
        char temp = str[i];
        str[i] = str[length - 1 - i];
        str[length - 1 - i] = temp;
    }
}

/*--- 10進数文字列変換(下位から変換)----------
 *   *str:変換結果を格納する文字列
 *    wd :変換したい符号無し16ビットデータ
 *-----------------------------------------------*/
void my_itoa2(char *str, uint16_t wd){
    uint8_t i;
    for(int i = 0; i < 6; i++){
        *str++ = '0' + (wd % 10);
        wd = wd / 10;
        if(wd == 0)	break;
    }
    *str = '\0';
}

/*---  10進数文字列変換 -------------------------
 *   *str:変換結果を格納する文字列
 *    wd :変換したい符号無し16ビットデータ
 *-----------------------------------------------*/
void my_itoa(char *str, uint16_t wd){
    my_itoa2(str, wd);
    reverseString(str);
}

/******* End of File ********/

 

/*********************************(myProject.h)*****
 *   プロジェクト個別条件指定ファイル  【強化版】  *
 *   (main.cと同じフォルダーに作成)              *
 ***************************************************/

#include "mcc_generated_files/mcc.h"
#include "string.h"

#define  ON    1
#define  OFF   0

/***** PIC電源電圧 ***********************/
//--- VCC宣言無しは5V(VCC=50と同じ)
//#define VCC   50                          / 電源電圧は5V
#define VCC   33                            // 電源電圧は3.3V

/***** EUSARTモジュール *******************/
#define EU_BFSIZE  40
//--- ECHO宣言無しはエコー有り(ECHO ONと同じ)
#define ECHO  ON                            // エコー有り
//#define ECHO  OFF                         // エコー無し

/*=== Eusart受信割り込みハンドラー ==============
 *    eusrt.cのEUSART_Recive_ISRに追加すること
 *---------------------------------------------*/
void myEusart();

/*=== 文字列シリアル出力関数 ===*/
//--- Eusartへ文字列送信
/*   *str: 出力する文字列
 * --------------------------- */
void EU_Write(char *str);

//--- Eusartへ改行を送信
void EU_Write_CR(void);

//--- Eusartへ文字列送信(改行付)
/*   *str: 出力する文字列
 * --------------------------- */
void EU_Puts(char *str);

/******  Delay Macros  ********/
#define __delay_us(x) _delay((uint32_t)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((uint32_t)((x)*(_XTAL_FREQ/4000.0)))

/***  自作汎用関数  *******/
/*==  文字列変換関数  ===========*/
//---- 16進文字列を10進数に変換
uint32_t my_xtol(char *str);

//---  16進数(負号無し)を文字列に変換
void my_utoa(char *str, uint16_t wd, uint8_t dg);

//---  10進数(符号無し)を文字列に変換
void my_itoa(char *str, uint16_t wd);

/******* End of File ********/

※プログラムのリストをハイライト無しのスタイルで見る場合はここをクリック


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


自転車用フラッシャー PICを3.3Vで使う