zoukankan      html  css  js  c++  java
  • [小黑科技] 破解一个电控升降桌,并改造成语音控制(上)—— 模拟中间人与控制手柄交互


    1、电路图破译

    其电路板如下,是一个程序员专用升降桌的控制手柄:

    简单看电路板,其原理图猜测是8路并转串,用来收集按键按下信息;两个串转8路并来驱动3个7段数码管:


    2、破解其数码管显示原理

    因此简单写一个74HC595串行写数据逻辑,分别写一些数据观察显示效果(代码基于ESP8266 RTOS的GPIO DEMO改造而来):

    #define GPIO_D4             2
    #define GPIO_D5             14
    #define GPIO_D6             12
    #define GPIO_D7             13
    #define GPIO_D8             15
    
    #define GPIO_SCK            GPIO_D5   
    #define GPIO_MISO           GPIO_D6
    #define GPIO_MOSI           GPIO_D7
    #define GPIO_NSS            GPIO_D4
    
    
    #define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_SCK) | (1ULL<<GPIO_MOSI) | (1ULL<<GPIO_NSS))
    #define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_MISO))
    
    
    static void gpio_task_example(void *arg)
    {
        int d = 0xFFDF;//待传输给74HC595的16bits数据
        int x = 0;
     
        while (1) {
            vTaskDelay(100 / portTICK_RATE_MS);
            gpio_set_level(GPIO_MOSI, (d>>x) & 0x01);//数据的一bit
            gpio_set_level(GPIO_SCK, 0);//SCK上升沿数据移入
            vTaskDelay(1 / portTICK_RATE_MS);
            gpio_set_level(GPIO_SCK, 1);
    
            x++;
            if(x == 16){//当所有16bits数据都送入了,NSS给一个上升沿,数据送到并口
                x=0;   
                gpio_set_level(GPIO_NSS, 0);
                vTaskDelay(1 / portTICK_RATE_MS);
                gpio_set_level(GPIO_NSS, 1);
            }
        }
    }
    
    void app_main(void)
    {
        gpio_config_t io_conf;
        //disable interrupt
        io_conf.intr_type = GPIO_INTR_DISABLE;
        //set as output mode
        io_conf.mode = GPIO_MODE_OUTPUT;
        //bit mask of the pins that you want to set,e.g.GPIO15/16
        io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
        //disable pull-down mode
        io_conf.pull_down_en = 0;
        //disable pull-up mode
        io_conf.pull_up_en = 0;
        //configure GPIO with the given settings
        gpio_config(&io_conf);
    
        //bit mask of the pins, use GPIO4/5 here
        io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
        //set as input mode
        io_conf.mode = GPIO_MODE_INPUT;
        //enable pull-up mode
        io_conf.pull_up_en = 1;
        gpio_config(&io_conf);
    
        //start gpio task
        xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
    
        while (1) {
            vTaskDelay(1000000 / portTICK_RATE_MS);
        }
    }
    

    其中74HC595的原理参考:https://blog.csdn.net/weixin_41445387/article/details/80500046
    其中3位数7段码类似这样:[#2]#2


    3、让数码管根据自己的意愿显示

    因此,数字0~9对应的编码如下(是16bits data的高8bits):

    数字 编码 十六进制
    0 1111 1100 0xFC
    1 0110 0000 0x60
    2 1101 1010 0xDA
    3 1111 0010 0xF2
    4 0110 0110 0x66
    5 1011 0110 0xB6
    6 1011 1110 0xBE
    7 1110 0000 0xE0
    8 1111 1110 0xFE
    9 1111 0110 0xF6

    让上述0~9数字显示在不同位是通过16bits中的低字节的高3bits实现的:

    编码
    百位 xxxx xxxx 0010 0000
    十位 xxxx xxxx 0100 0000
    个位 xxxx xxxx 1000 0000

    如果想要显示一个3位数,是通过快速显示个十百位来实现的,代码实现如下:

    char digital[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6};//0~9
    char position[3] = {0x80,0x40,0x20};//百十个
    
    void app_show_digital(int d){//显示1位数字
        for(int i=0;i<16;i++){
            gpio_set_level(GPIO_MOSI, (d>>i) & 0x01);
            gpio_set_level(GPIO_SCK, 0);
            gpio_set_level(GPIO_SCK, 1);
        }
    
        gpio_set_level(GPIO_NSS, 0);
        gpio_set_level(GPIO_NSS, 1);
    }
    
    void app_show_num(int num){//分时复用显示3位数字
        if(num < 0 || num > 999)return;
    
        static int show_pos = 0;
        int gsb[3];//个十百
        gsb[0] = digital[num%10];//个
        gsb[1] = digital[num/10%10];//十
        gsb[2] = digital[num/100];//百
        app_show_digital(gsb[show_pos] << 8 | position[show_pos]);
    
        show_pos++;
        if(show_pos == 3)show_pos = 0;
    }
    
    int show_num = 0;
    static void gpio_task_example(void *arg)
    {
        while (1) {
            app_show_num(show_num);
            vTaskDelay(9 / portTICK_RATE_MS);
        }
    }
    

    注:这里有一点要注意,在make config中,将RTOS的频率从100Hz调到200Hz,否则vTaskDelay(10 / portTICK_RATE_MS) 中10以下的值全都作为0处理,会导致看门狗被饿死而系统重启(看门狗的26.1S超时也在config中)


    4、破解其按键操作逻辑

    简单写一个74HC165串行读数据逻辑,用串口将读取的数据打印下来(代码基于ESP8266 RTOS的GPIO DEMO改造而来):

    char app_read_key(void){
        char data = 0;
        for(int i=0;i<8;i++){
            gpio_set_level(GPIO_SCK, 0);
            gpio_set_level(GPIO_SCK, 1);
            char bit = gpio_get_level(GPIO_MISO) == 0?0:1;
            data <<= 1;
            data |= bit;
        }
        return data;
    }
    
    int show_num = 0;
    static void gpio_task_example(void *arg)
    {
        while (1) {
            app_show_num(show_num);
            ESP_LOGI(TAG, "key: %X
    ", app_read_key());
            vTaskDelay(9 / portTICK_RATE_MS);
        }
    }
    

    按动不同按键,看读取的数据:

    按键 CODE 二进制
    不按 7F 0111 1111
    L1 上 7D 0111 1101
    L2 下 7B 0111 1011
    L3 一档 77 0111 0111
    L4 二档 6F 0110 1111
    L5 三档 5F 0101 1111
    L6 四档 3F 0011 1111


    : 小黑科技:将非智能升降桌改为智能升降桌
    大家觉得不错,可以点推荐给更多人~

    [1]. 亮红色共阳0.36英寸3位数码管共阴红光3361AS/BS
    [2]. 单片机芯片之——图解74HC595(第一部分)
    [3]. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明


    @beautifulzzzz
    以蓝牙技术为基础的的末梢无线网络系统架构及创新型应用探索!
    领域:智能硬件、物联网、自动化、前沿软硬件
    博客:https://www.cnblogs.com/zjutlitao/
    微信交流群|微信:园友交流群|btfzzzz
    
  • 相关阅读:
    [原创]java WEB学习笔记26:MVC案例完整实践(part 7)---修改的设计和实现
    [原创]java WEB学习笔记25:MVC案例完整实践(part 6)---新增操作的设计与实现
    [原创]java WEB学习笔记24:MVC案例完整实践(part 5)---删除操作的设计与实现
    [原创]java WEB学习笔记23:MVC案例完整实践(part 4)---模糊查询的设计与实现
    Tapestry IoC Configuration
    Tapestry IoC Decorator
    Tapestry IoC Service
    Tapestry-Again
    mysql error nr.1045 解决方法
    Bootstrap学习 导航
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/11525228.html
Copyright © 2011-2022 走看看