1. Arduino驱动4寸CRT

1.1. 材料


开发板、显示器、电源部分

总计:46元


12v纯平黑白CRT
¥:25元

1.2. 结构

暂无

1.3. 代码

暂无

1.4. 效果演示

项目仅仅是设想

2. 使用Arduino制作万用表

3. 将1、2项目合并为一个

4. 8x5x7VFD点阵屏时钟

4.1. 材料


开发板、VFD、温湿度、光强、触摸、ds3102、电源部分、其他材料

总计:82元


8x7x5点阵屏

¥:35元

  1. 温湿度AHT10-----¥5
  2. MAX44009-------¥7
  3. DS3102---------¥3
  4. TTP223开关------¥0.4

¥:16元


充放一体板

¥:7元


外壳木板、以及胡桃木皮

¥:13元

4.2. 结构

4.3. 代码

代码部分

/******************************************************************************
-------------------------1.开发环境:Arduino IDE-----------------------------------
-------------------------------2.作者:starky-----------------------------------------
DS1302:from https://www.jianshu.com/p/142435a024a1
******************************************************************************/
#include <Arduino.h>
#include "DS1302.h"

#include "Arduino.h" //用于包含如ADMUX等寄存器的宏
//code from:https://blog.csdn.net/u013810296/article/details/86746666
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1))
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#define ADMUX_VCCWRT1V1 (_BV(MUX5) | _BV(MUX0))
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define ADMUX_VCCWRT1V1 (_BV(MUX3) | _BV(MUX2))
#else
#define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1))
#endif
float Read_Volts(void)
{
    // Read 1.1V reference against AVcc
    // set the reference to Vcc and the measurement to the internal 1.1V reference
    if (ADMUX != ADMUX_VCCWRT1V1)
    {
        ADMUX = ADMUX_VCCWRT1V1;

        // Bandgap reference start-up time: max 70us
        // Wait for Vref to settle.
        delayMicroseconds(350);
    }

    // Start conversion and wait for it to finish.
    ADCSRA |= _BV(ADSC);
    while (bit_is_set(ADCSRA, ADSC)) {};

    // Result is now stored in ADC.

    // Calculate Vcc (in V)
    float vcc = 1.1 * 1024.0 / ADC;

    return vcc;
}

//arduino uno r3 引脚接法

uint8_t din = 8; // DA
uint8_t clk = 7; // CK
uint8_t cs = 6; // CS
uint8_t Reset = 1; // RS
uint8_t en = 0; // EN
uint8_t CTL1 = 9;  //mode
uint8_t dim = 100;  //dim
const int CTL2 = 10;  //set
boolean switch_state = true;
int tomato_time = 20;

int h1 = 0;
int h2 = 0;
int m1 = 0;
int m2 = 0;
int s1 = 0;
int s2 = 0;

void write_6302(unsigned char w_data)
{
    unsigned char i;
    for (i = 0; i < 8; i++)
    {
        digitalWrite(clk, LOW);
        if ((w_data & 0x01) == 0x01)
        {
            digitalWrite(din, HIGH);
        }
        else
        {
            digitalWrite(din, LOW);
        }
        w_data >>= 1;
        digitalWrite(clk, HIGH);
    }
}

void VFD_cmd(unsigned char command)
{
    digitalWrite(cs, LOW);
    write_6302(command);
    digitalWrite(cs, HIGH);
    delayMicroseconds(1);
}

void S1201_show(void)
{
    digitalWrite(cs, LOW);//开始传输
    write_6302(0xe8);     //地址寄存器起始位置
    digitalWrite(cs, HIGH); //停止传输
}

void VFD_init()
{
    //SET HOW MANY digtal numbers
    digitalWrite(cs, LOW);
    write_6302(0xe0);
    delayMicroseconds(5);
    write_6302(0x07);//8 digtal
    digitalWrite(cs, HIGH);
    delayMicroseconds(5);

    //set bright
    digitalWrite(cs, LOW);
    write_6302(0xe4);
    delayMicroseconds(5);
    write_6302(0x0f);//leve 255 max
    digitalWrite(cs, HIGH);
    delayMicroseconds(5);
}

void VFD_dim(unsigned char dim)
{
    //set bright
    digitalWrite(cs, LOW);
    write_6302(0xe4);
    delayMicroseconds(5);
    write_6302(dim);//leve 255 max
    digitalWrite(cs, HIGH);
    delayMicroseconds(5);
}

/******************************
  在指定位置打印一个number(用户自定义,所有CG-ROM中的)
  x:0~11;chr:要显示的字符编码
*******************************/
void S1201_WriteOneChar(unsigned char x, unsigned char chr)
{
    digitalWrite(cs, LOW);  //开始传输
    write_6302(0x20 + x); //地址寄存器起始位置
    write_6302(chr + 0x30);
    digitalWrite(cs, HIGH); //停止传输
    S1201_show();
}


/******************************
  在指定位置打印一个字符(用户自定义,所有CG-ROM中的)
  x:0~11;chr:要显示的字符编码
*******************************/
void S1201_WriteOneChar1(unsigned char x, unsigned char chr)
{
    digitalWrite(cs, LOW);  //开始传输
    write_6302(0x20 + x); //地址寄存器起始位置
    write_6302(chr);
    digitalWrite(cs, HIGH); //停止传输
    S1201_show();
}

/******************************
  在指定位置打印字符串
  (仅适用于英文,标点,数字)
  x:0~11;str:要显示的字符串
*******************************/
void S1201_WriteStr(unsigned char x, char* str)
{
    digitalWrite(cs, LOW);  //开始传输
    write_6302(0x20 + x); //地址寄存器起始位置
    while (*str)
    {
        write_6302(*str); //ascii与对应字符表转换
        str++;
    }
    digitalWrite(cs, HIGH); //停止传输
    S1201_show();
}


void S1201_WriteNumShade(unsigned char x, unsigned char chr, int delaytime)
{
    int slot = 10;
    int times = delaytime / slot;
    int i = 0;
    for (i = 0; i < times; i++)
    {
        S1201_WriteOneChar(x, chr);
        delay(slot);
        VFD_dim((255 * (delaytime - i * slot)) / delaytime);
    }
}

void S1201_WriteNumLight(unsigned char x, unsigned char chr, int delaytime)
{
    int slot = 10;
    int times = delaytime / slot;
    int i = 0;
    for (i = times; i > 0; i++)
    {
        S1201_WriteOneChar(x, chr);
        delay(slot);
        VFD_dim((255 * (i * slot)) / delaytime);
    }
}


void Zero_time()
{
    h1 = -1;
    h2 = -1;
    m1 = -1;
    m2 = -1;
    s1 = -1;
    s2 = -1;
}

//显示时间
void Display_RTCC()
{

    if (DS1302Buffer.Second == 57)//57秒的时候显示年月日
    {
        if (DS1302Buffer.Year >= 10)
        {
            int year1 = DS1302Buffer.Year / 10;
            int year2 = DS1302Buffer.Year % 10;
            S1201_WriteOneChar(0, year1);
            S1201_WriteOneChar(1, year2);

        }
        S1201_WriteOneChar1(2, '-');
        int mon1 = DS1302Buffer.Month / 10;
        int mon2 = DS1302Buffer.Month % 10;
        S1201_WriteOneChar(3, mon1);
        S1201_WriteOneChar(4, mon2);
        S1201_WriteOneChar1(5, '-');
        int day1 = DS1302Buffer.Day / 10;
        int day2 = DS1302Buffer.Day % 10;
        S1201_WriteOneChar(6, day1);
        S1201_WriteOneChar(7, day2);
        delay(1000);
        Zero_time();

    }
    else if (DS1302Buffer.Second == 58)//58的时候显示星期
    {
        switch (DS1302Buffer.Week)
        {
        case 1:
            S1201_WriteStr(0, "Monday:)");         //显示星期一
            break;
        case 2:
            S1201_WriteStr(0, "TUESDAY2");          //显示星期二
            break;
        case 3:
            S1201_WriteStr(0, "WEDNESDY");          //显示星期三
            break;
        case 4:
            S1201_WriteStr(0, "THURSDAY");          //显示星期四
            break;
        case 5:
            S1201_WriteStr(0, "FRIDAY:)");          //显示星期五
            break;
        case 6:
            S1201_WriteStr(0, "STAURDAY");          //显示星期六
            break;
        case 7:
            S1201_WriteStr(0, "SUNDAY:)");          //显示星期日
            break;
        default: break;
        }
        delay(1000);
        Zero_time();

    }
    else
    {
        //int slot = 10;
        //int half_times = 500/10;

        int hour1 = DS1302Buffer.Hour / 10;
        int hour2 = DS1302Buffer.Hour % 10;
        if (hour1 != h1 )
            S1201_WriteOneChar(0, hour1);
        if (hour2 != h2 )
            S1201_WriteOneChar(1, hour2);

        S1201_WriteOneChar1(2, ':');
        S1201_WriteOneChar1(5, ':');

        int mins1 = DS1302Buffer.Minute / 10;
        int mins2 = DS1302Buffer.Minute % 10;
        if (mins1 != m1 )
            S1201_WriteOneChar(3, mins1);
        if (mins2 != m2 )
            S1201_WriteOneChar(4, mins2);


        int sec1 = DS1302Buffer.Second / 10;
        int sec2 = DS1302Buffer.Second % 10;
        if (sec1 != s1 )
            S1201_WriteOneChar(6, sec1);
        if (sec2 != s2 )
            S1201_WriteOneChar(7, sec2);
        delay(500);
        S1201_WriteOneChar1(2, ' ');
        S1201_WriteOneChar1(5, ' ');
        delay(500);

        h1 = hour1;
        h2 = hour1;
        m1 = mins1;
        m2 = mins2;
        s1 = sec1;
        s2 = sec2;

    }


}

//开关是否按下函数
boolean press_switch()
{
    boolean now_state = digitalRead(CTL1);
    if (now_state != switch_state)
    {
        switch_state = now_state;
        return true;
    }
    else
        return false;
}



//时间设置函数
void Set_Time1(int year, int month, int day, int week, int hour, int mins, int secs)
{
    DS1302_ON_OFF(0);     //关闭振荡
    DS1302Buffer.Year = year;
    DS1302Buffer.Month = month;
    DS1302Buffer.Day = day;
    DS1302Buffer.Week = week;
    DS1302Buffer.Hour = hour;
    DS1302Buffer.Minute = mins;
    DS1302Buffer.Second = secs;
    DS1302_SetTime(DS1302_YEAR, DS1302Buffer.Year);
    DS1302_SetTime(DS1302_MONTH, DS1302Buffer.Month);
    DS1302_SetTime(DS1302_DAY, DS1302Buffer.Day);
    DS1302_SetTime(DS1302_WEEK, DS1302Buffer.Week);
    DS1302_SetTime(DS1302_HOUR, DS1302Buffer.Hour);
    DS1302_SetTime(DS1302_MINUTE, DS1302Buffer.Minute);
    DS1302_SetTime(DS1302_SECOND, DS1302Buffer.Second);
    DS1302_ON_OFF(1);


    Display_RTCC();
}


void tomato(int i)
{
    int j = i;
    boolean c = press_switch();
    while (c == false && j > 0)
    {
        print_tomato_time(j);
        j -= 1;      
        c = press_switch();
    }
    if (c == true) return;

    take_rest();
    S1201_WriteStr(0, "Go on ??");
    delay(3000);

    if (press_switch() == true)
    {
        tomato(tomato_time);
    }


    
}


//番茄时间打印函数
void print_tomato_time(int i)
{
    int mins = (i % 3600) / 60;
    int mins1 = mins / 10;
    int mins2 = mins % 10;
    int sec = (i % 3600) % 60;
    int sec1 = sec / 10;
    int sec2 = sec % 10;
    S1201_WriteOneChar1(0, 'R');
    S1201_WriteOneChar1(1, 'M');

    S1201_WriteOneChar(3, mins1);
    S1201_WriteOneChar(4, mins2);
    S1201_WriteOneChar(6, sec1);
    S1201_WriteOneChar(7, sec2);

    S1201_WriteOneChar1(2, ':');
    S1201_WriteOneChar1(5, '-');
    delay(500);


    S1201_WriteOneChar1(2, ' ');
    S1201_WriteOneChar1(5, ' ');


    delay(500);

    


}
//番茄休息时间
void take_rest()
{
    int slot = 220;
    S1201_WriteStr(0, ":-) TAKE");
    delay(slot);
    S1201_WriteStr(0, ":-) AKE ");
    delay(slot);
    S1201_WriteStr(0, ":-) KE A");
    delay(slot);
    S1201_WriteStr(0, ":-) E A R");
    delay(slot);
    S1201_WriteStr(0, ":-)  A RE");
    delay(slot);
    S1201_WriteStr(0, ":-) A RES");
    delay(slot);
    S1201_WriteStr(0, ":-) REST");
    delay(slot);
    int i = 10;
    while ((i >= 0) && press_switch() == false)
    {

        int mins = (i % 3600) / 60;
        int mins1 = mins / 10;
        int mins2 = mins % 10;
        int sec = (i % 3600) % 60;
        int sec1 = sec / 10;
        int sec2 = sec % 10;

        S1201_WriteOneChar1(0, ':');
        S1201_WriteOneChar1(1, '-');
        S1201_WriteOneChar1(2, 'D');
        S1201_WriteOneChar1(3, ' ');
        S1201_WriteOneChar(4, mins1);
        S1201_WriteOneChar(5, mins2);
        S1201_WriteOneChar(6, sec1);
        S1201_WriteOneChar(7, sec2);

        delay(500);


        S1201_WriteOneChar1(0, ':');
        S1201_WriteOneChar1(1, '-');
        S1201_WriteOneChar1(2, ')');
        delay(500);
        i -= 1;
    }
}


//打印函数
void print_tomato()
{
    int slot = 170;
    S1201_WriteStr(0, "        ");
    delay(slot);
    S1201_WriteStr(0, "      <-");
    delay(slot);
    S1201_WriteStr(0, "     <--");
    delay(slot);
    S1201_WriteStr(0, "    <---");
    delay(slot);
    S1201_WriteStr(0, "   <---F");
    delay(slot);
    S1201_WriteStr(0, "  <---FO");
    delay(slot);
    S1201_WriteStr(0, " <---FOC");
    delay(slot);
    S1201_WriteStr(0, "----FOCU");
    delay(slot);
    S1201_WriteStr(0, "---FOCUS");
    delay(slot);
    S1201_WriteStr(0, "--FOCUS ");
    delay(slot);
    S1201_WriteStr(0, "-FOCUS O");
    delay(slot);
    S1201_WriteStr(0, "FOCUS ON");
    delay(slot);
    S1201_WriteStr(0, "OCUS ON ");
    delay(slot);
    S1201_WriteStr(0, "CUS ON A");
    delay(slot);
    S1201_WriteStr(0, "US ON A ");
    delay(slot);
    S1201_WriteStr(0, "S ON A T");
    delay(slot);
    S1201_WriteStr(0, " ON A TO");
    delay(slot);
    S1201_WriteStr(0, "ON A TOM");
    delay(slot);
    S1201_WriteStr(0, "N A TOMA");
    delay(slot);
    S1201_WriteStr(0, " A TOMAT");
    delay(slot);
    S1201_WriteStr(0, "A TOMATO");
    delay(slot);
    S1201_WriteStr(0, " TOMATO ");
    delay(slot);
    S1201_WriteStr(0, "TOMATO T");
    delay(slot);
    S1201_WriteStr(0, "OMATO TI");
    delay(slot);
    S1201_WriteStr(0, "MATO TIM");
    delay(slot);
    S1201_WriteStr(0, "ATO TIME");
    delay(slot);
    S1201_WriteStr(0, "TO TIME ");
    delay(slot);
    S1201_WriteStr(0, "O TIME ~");
    delay(slot);
    S1201_WriteStr(0, " TIME ~ ");
    delay(slot);
    S1201_WriteStr(0, "TIME ~  ");
    delay(slot);
    S1201_WriteStr(0, "IME ~   ");
    delay(slot);
    S1201_WriteStr(0, "ME ~    ");
    delay(slot);
    S1201_WriteStr(0, "E ~     ");
    delay(slot);
    S1201_WriteStr(0, " ~      ");
    delay(slot);
}
void print_bye()
{
    int slot = 300;
    S1201_WriteStr(0, "---BYE--");
    delay(slot);
    S1201_WriteStr(0, "        ");
    delay(slot);
    S1201_WriteStr(0, "---BYE--");
    delay(slot);
    S1201_WriteStr(0, "        ");
    delay(slot);


}
void print_bat()
{
    float vcc = Read_Volts();
    int v = int(vcc * 100);//398
    int v1 = v / 100;//3
    int v2 = (v - v1 * 100) / 10;//9
    int v3 = (v - v1 * 100) % 10;//8
    S1201_WriteOneChar1(0, 'V');
    S1201_WriteOneChar1(1, 'C');
    S1201_WriteOneChar1(2, 'C');
    S1201_WriteOneChar1(3, ':');
    S1201_WriteOneChar(4, v1);
    S1201_WriteOneChar1(5, '.');
    S1201_WriteOneChar(6, v2);
    S1201_WriteOneChar(7, v3);
    delay(1000);

    S1201_WriteOneChar1(0, 'B');
    S1201_WriteOneChar1(1, 'a');
    S1201_WriteOneChar1(2, 't');
    S1201_WriteOneChar1(3, ':');
    S1201_WriteOneChar1(4, ' ');
    S1201_WriteOneChar1(7, '%');

    if (v > 420)
    {
        S1201_WriteOneChar(4, 1);
        S1201_WriteOneChar(5, 0);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 406)
    {
        S1201_WriteOneChar(5, 9);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 398)
    {
        S1201_WriteOneChar(5, 8);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 392)
    {
        S1201_WriteOneChar(5, 7);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 387)
    {
        S1201_WriteOneChar(5, 6);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 382)
    {
        S1201_WriteOneChar(5, 5);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 379)
    {
        S1201_WriteOneChar(5, 4);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 377)
    {
        S1201_WriteOneChar(5, 3);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 374)
    {
        S1201_WriteOneChar(5, 2);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 368)
    {
        S1201_WriteOneChar(5, 1);
        S1201_WriteOneChar(6, 0);
    }
    else if (v > 345)
    {
        S1201_WriteOneChar(5, 0);
        S1201_WriteOneChar(6, 5);
    }

    else
    {
        S1201_WriteOneChar(5, 0);
        S1201_WriteOneChar(6, 0);
    }

    delay(1000);

}

void print_dim()
{

    int i = (100 * dim) / 255;
    int i1 = i / 100;//3
    int i2 = (i - i1 * 100) / 10;//9
    int i3 = (i - i1 * 100) % 10;//8
    S1201_WriteOneChar1(0, 'D');
    S1201_WriteOneChar1(1, 'i');
    S1201_WriteOneChar1(2, 'm');
    S1201_WriteOneChar1(3, ':');
    if (i1 != 0)
        S1201_WriteOneChar(4, i1);
    else
        S1201_WriteOneChar1(4, ' ');


    S1201_WriteOneChar(5, i2);


    S1201_WriteOneChar(6, i3);

    S1201_WriteOneChar1(7, '%');
    delay(1000);
}

void setup()
{
    DS1302_Init();
    DS1302_GetTime(&DS1302Buffer);
    Display_RTCC();
    //Set_Time1(20, 9, 17, 4, 17, 54, 0);
    pinMode(en, OUTPUT);
    pinMode(clk, OUTPUT);
    pinMode(din, OUTPUT);
    pinMode(cs, OUTPUT);
    pinMode(Reset, OUTPUT);
    pinMode(CTL1, INPUT);
    pinMode(CTL2, INPUT);
    digitalWrite(en, HIGH);
    digitalWrite(Reset, LOW);
    delayMicroseconds(5);
    digitalWrite(Reset, HIGH);
    VFD_init();
    VFD_cmd(0xE9);// 全亮
    VFD_dim(30);
    switch_state = digitalRead(CTL1);
    Zero_time();
}

int i = 0;


void loop()
{
    DS1302_GetTime(&DS1302Buffer);        //获取当前RTCC值
    int vcc = int(Read_Volts() * 100);
    if (vcc < 380)//省电模式
    {
        S1201_WriteStr(0, "        ");
        if ((DS1302Buffer.Second >= 57 && DS1302Buffer.Second <= 59) || (DS1302Buffer.Second == 0) || (DS1302Buffer.Second == 1))
        {
            Display_RTCC();
        }
    }
    else//正常模式
    {

        if (DS1302Buffer.Second % 58 == 0 && DS1302Buffer.Minute % 3 == 0)//每三分钟输出电池信息
        {
            print_bat();
            Zero_time();
        }
        else
        {
            Display_RTCC();
        }

        if (press_switch() == true)//番茄时钟倒计时模式
        {
            VFD_dim(40);
            //显示番茄时钟
            print_tomato();
            tomato(tomato_time);
            print_bye();
            Zero_time();
        }
    }



}

4.4. 效果演示

完善中

5. Arduino使用MCP23017驱动HDPL1414

5.1. 材料


开发板、MCP23017、HDPL1414、PCB板、电源部分

总计:43元


MCP23017
¥:7元

HDPL1414*2
¥:10元

PCB设计制作、学习成本大
¥:10元

锂电冲放保护一体板
¥:5元

5.2. 结构

暂无

5.3. 代码

HPDL点亮参见

参照此链接

5.4. 效果演示

预备阶段

……
待续
……

最后修改:2020 年 12 月 04 日 11 : 12 PM
如果觉得我的文章对你有用,请随意赞赏