果報は寝て待て: 7月 2023

2023年7月5日水曜日

7segカウンターで遊ぶ

 アマゾンで1万円ちょいで中華製の大型LEDを買った。


 

 目的は、工場のあるライン内の、ある工程で払い出されたNG品の数をメイン通路の誰でも見やすい位置に表示することです。

要求は、大きい数字で表示できる。

一台ずつカウントアップできる。

リセットで0にできる。

最後に、責任者が確認したら、OK品だった場合のカウントダウンできることです。

しかし説明書にはカウントダウンできるとはどこにも書いてません。そこでまず1台買って改造できるか調べます。

製品の裏蓋を外した状態です。


PIC12F675が中央にあり、7SEGLED専用ドライバーのTM1620が右端に見えます。

ピンの接続は、

1-VDD, 

2-デジタルI/Oでカウントアップ、

3-デジタルI/Oでカウントを0にセット

4-未使用

5-データ送信

6-クロック送信

7-ストローブ信号送信

8-Vss

そう。4番ピンが余ってる。なんとかしてみよう。

ロジアナで[24]を表示している時の信号です。上から STB,CLOCK,DATAです。


データシートや他のかたのコードを参考にして、同じ数字のときに同じ信号になるようにコードを書きます。

 結論から言うと、データシートどおりでは無いところが2箇所ありました。

1 1桁目の数字はGRID1に表示され、2桁目の数字はGRID6に表示されます。

  3桁目以降の位置は不明。

2 SEG1=a,

  SEG2=b ・・・ SEG7=g のところ

     SEG1=d   ,SEG2=常時0    , SEG3=g     ,SEG4=a     ,SEG5=b    ,SEG6=c    SEG7=f  

        SEG8=c となってます。

これを加味したのが以下のコードです。マイコンはpic12f1822。そのままポン付けできそうなので…


/*
 * File:   main.c
 * Author: Administrator
 *
 * Created on April 11, 2023, 10:48 PM
 */
// PIC12F1822 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000

#define STB RA0
#define CLK RA1
#define DIO RA2
#define count_up RA5
#define reset RA4
#define count_down RA3

const char NUM[11] = {
    0b11111001,    //0
    0b10010000,    //1
    0b10101101,    //2
    0b10011101,    //3
    0b11010100,    //4
    0b01011101,    //5
    0b01111101,    //6
    0b10011000,    //7
    0b11111101,    //8
    0b11011101,    //9
    0b00000000     //void
};

void Init();
void TM_Send(char data);
void NumToArr( int n, char* arr);
void TM_ShowNum( int n){   // 0<= n <= 999999
    char arr[6];
    NumToArr(n , arr);
    
    STB = 0;
    TM_Send(0b00000011);    //6X8
    STB = 1;
    __delay_us(9);
    STB = 0;
    TM_Send(0b01000000);    //Address auto increment
    STB = 1;
    __delay_us(9);
    STB = 0;
    TM_Send(0b11000000);    //Address SET
    
    TM_Send(NUM[arr[5]]);      //Charactor Data 1
    for(char i=0; i<9; i++){
        TM_Send(0);                //Dummy
    }
    TM_Send(NUM[arr[4]]);      //Charactor Data 10
    TM_Send(0);                //Dummy
    STB = 1;
    __delay_us(9);
    STB = 0;
    TM_Send(0x8f);                 //Duty 14 /16(max)
    DIO = 0;
    STB = 1;
}

void TM_Init(){
    STB = 1;
    CLK = 1;
    
    STB = 0;
    TM_Send(0x02);                 //6x8
    STB = 1;
    __delay_us(6);
    STB = 0;
    TM_Send(0x40);                 //Address auto increment
    STB = 1;
    __delay_us(6);
    TM_ShowNum(0);
    __delay_us(6);
    STB = 0;
    TM_Send(0x8f);                 //Duty 14 /16(max)
    STB = 1;
}

void main(void) {
    Init();
    TM_Init();
    OSCCON = 0b01110000;
    WPUA = 0xFF;
    OPTION_REGbits.nWPUEN = 0;
    int count = 0;
    int up_flug = 0;
    int down_flug = 0;
    
    while(1){
        TM_ShowNum(count);
        //count ++;
        __delay_ms(10);  // 50
        if (count_up == 0){
            if(up_flug == 0){
                count ++ ;
                up_flug = 1;
            }
        }
        else{
            if(up_flug == 1){
                 up_flug = 0;
            }
        }
        
        if (count_down == 0){
             if(down_flug == 0 & count > 0 ){
                  count -- ;
                  down_flug = 1;
            }
        }
        else{
            if(down_flug == 1){
                 down_flug = 0;
            }
        }
        if (reset == 0){
            count = 0;
        }
    }
}

void Init(){
    ANSELA = 0;
    TRISA = 0b00111000;
    
    
}
void TM_Send(char data){
    for(char i=0; i<8; i++){
        CLK = 0;
        DIO = (data) & 0x1;
        data = data>>1;
        __delay_us(1);
        CLK = 1;
    }
    __delay_us(1);
    DIO = 0;
}
void NumToArr(int n, char* arr){
    for(char i=0; i<6; i++){             //sprit n into arr
        arr[5-i] = n % 10;
        n /= 10;
    }
    for(char i=0; i<5; i++){           //delete initial zero
        if(arr[i] == 0 )
            arr[i]  = 10;              //void
        else break;
    }
}

計算は6桁まで  (本当は32767まで)できるのですが、2桁しか表示されません。

そのうち上限を99にするようコードを書き換えるでしょう。  

4番ピンは期待通りカウントダウンしてくれました。