尝试用LCD与树莓派Pico 2控制步进电机

编程语言 2026-07-11

我有一个LCD触控屏连接在我的Raspberry Pi Pico 2开发板上。我的目标是在屏幕上检测触摸,当用户点按屏幕时让步进电机开始旋转。电机通过GPIO引脚进行控制。

我遇到的问题是,在触摸事件发生后,步进电机的转速比预期慢得多。我不确定问题是否出在驱动电机的方式、每步之间的延时,还是代码中对触控交互的处理。

我希望在屏幕被触摸后,电机能立即启动并以更高的速度旋转。造成电机运行如此缓慢的原因可能是什么,我又怎样提升性能?

#include <stdio.h>
#include "pico/stdlib.h"

#include "tft_lcd_ili9341/gfx/gfx_ili9341.h"
#include "tft_lcd_ili9341/ili9341/ili9341.h"
#include "tft_lcd_ili9341/touch_resistive/touch_resistive.h"

#include "image_bitmap.h"           


#define SCREEN_ROTATION 1           
const int width = 320;             
const int height = 240;            

const int BOBINAS[4] = {5, 4, 3, 2};


const int  rotImgPosX = (width - 32) / 2;
const int  rotImgPosY = (height - 24) / 2;


int f_btn = 0;
volatile int motor_state = 0;
volatile int imagem_state = 0;


void ledButtonCallback(GFX_Button *btn) {
    f_btn = 1;
}


int direcao = 1;

void drawImagem(int estado) {
    gfx_fillRect(rotImgPosX, rotImgPosY, 32, 24, 0x0000);
    if (direcao == 1){ //horario
        if (estado == 0)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, horario_1, 24, 32, 0xFFFF); 
    else if(estado == 1)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, horario_2, 32, 24, 0xFFFF);
    else if (estado == 2)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, horario_3, 24, 32, 0xFFFF); 
    else if (estado == 3)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, horario_4, 32, 24, 0xFFFF); 

    }
    else if (direcao == -1){ //æntihorario
        if (estado == 0)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, anti_horario_4, 32, 24, 0xFFFF); 
    else if(estado == 1)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, anti_horario_3, 24, 32, 0xFFFF); 
    else if (estado == 2)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, anti_horario_2, 32, 24, 0xFFFF); 
    else if (estado == 3)
        gfx_drawBitmap(rotImgPosX, rotImgPosY, anti_horario_1, 24, 32, 0xFFFF); 
    }


}

bool timer_motor_callback(struct repeating_timer *t) {
    motor_state = 1; // Alterna o estado do motor    
    return true; // Retorna true para continuar o timer
}

bool timer_imagem_callback(struct repeating_timer *t) {
    imagem_state = 1;
    return true;
}


int main() {
    repeating_timer_t timer_motor;
    repeating_timer_t timer_imagem;

    stdio_init_all();

    for (int i = 0; i < 4; i++) {
        gpio_init(BOBINAS[i]);
        gpio_set_dir(BOBINAS[i], GPIO_OUT);
    }




    LCD_initDisplay();
    LCD_setRotation(SCREEN_ROTATION);   


    configure_touch();                  

    gfx_init();                        
    gfx_clear();                      

    gfx_setTextSize(2);                                 
    gfx_setTextColor(0x07E0);                           

    gfx_drawText(
        width/6,                                       
        10,                                             
        "PicoDock LED Toggle"                           
    );



    GFX_Button ledButton = {            
        .x = rotImgPosX,                
        .y = rotImgPosY,                
        .w = 32,                        
        .h = 32,                        
        .callback = ledButtonCallback   
    };

    gfx_registerButton(&ledButton);     

    int i = 0;
    int motor_on = 0;
    int img = 0;

    drawImagem(img);

    add_repeating_timer_us(1000, timer_motor_callback, NULL, &timer_motor);
    add_repeating_timer_ms(500, timer_imagem_callback, NULL, &timer_imagem);

    while (true) {
        int touchRawX, touchRawY;               
        int screenTouchX, screenTouchY  = 0;    

        int touchDetected = readPoint(&touchRawX, &touchRawY);  


        if (touchDetected)  {                                                       
            gfx_touchTransform(SCREEN_ROTATION,                 
                               touchRawX, touchRawY,            
                               &screenTouchX, &screenTouchY);


            gfx_updateButtons(screenTouchX, screenTouchY, touchDetected);   

        }

        if (f_btn) {

            direcao = -direcao; 
            motor_on = 1;
            drawImagem(img);    
            f_btn = 0;
        }



        if (motor_state && motor_on) {
            motor_state = 0;

            for (int k = 0; k < 4; k++) {
                gpio_put(BOBINAS[k], 0);
            }

            if (direcao == 1){
                gpio_put(BOBINAS[i], 1);
            }

            else {
                gpio_put(BOBINAS[3 - i], 1);
            }


            i = (i + 1) % 4;


        }

        if (imagem_state && motor_on) {
            imagem_state = 0;
            img = (img + 1) % 4;
            drawImagem(img);
        }

    }

    return 0;
}

解决方案

GPIO引脚可能无法提供足够的电流来驱动电机。你应该改用逻辑电平MOSFET/晶体管来进行开关,然后通过一个合适的电阻把GPIO引脚连接到栅极/基极。此外,电机是感性负载,在关断时会产生电压尖峰,可能会损坏你的Pico。你应该在电机两端并联一个反向偏置的二极管(接法为“反向连接”,阴极连正极,阳极连负极),例如1N4007。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章