Преобразование аналогового 0-5В в эквивалент поворотного энкодера

В настоящее время я работаю над роботом в качестве стажера и должен выбрать замену драйверов для двигателей. Информация о положении оси задается аналоговым горшком. У меня есть 3 драйвера от technosoft, которым требуется информация о вращающемся энкодере (квадратурах) для выполнения их работы по регулированию. Я думал о преобразовании этого аналогового сигнала в правильный квадратурный сигнал, чтобы он работал.

То, как я это спроектировал, это рис. 18, который выбирает значение банка с частотой 150 Гц, вычитая предыдущее значение из текущего, чтобы иметь представление (своего рода вывод) о скорости. Он генерирует абсолютное значение скорости и сигнал направления, который регулирует скорость изменения конечного автомата с помощью 4 состояний квадратурного энкодера. Я наконец посылаю эти сигналы на 2 выхода.

Мои вопросы следующие.

Это возможно. Или есть умный способ сделать это? Или даже специальный чип, который может сделать эту работу? Я искал в Интернете кого-то, кто уже сделал бы что-то подобное, но ничего не нашел.

Последние два дня я потратил на то, чтобы кодировать это решение и безуспешно отлаживать его... В области видимости есть квадратурный сигнал, но он ведет себя без реальной логики. Меняется очень быстро или медленно, двигаюсь ли я или не двигаю банк.

Вот мой код

#include <p18f4685.h>
#include <stdlib.h>
#include <stdio.h>  
#include <delays.h> 

// ----------------------
// Configuration Hardware
// ----------------------

#pragma config OSC = HSPLL
#pragma config MCLRE = ON, PWRT = OFF
#pragma config DEBUG = ON, LVP = OFF
#pragma config  FCMEN = OFF
#pragma config  IESO = OFF          
#pragma config  BOREN = OFF 
#pragma config  WDT = OFF
#pragma config  XINST = OFF

#pragma code

// Variables

unsigned int position_t0=0;                 
unsigned int position_t1=0;
signed int speed=0;
unsigned int speed_abs=0;
int direction=0; // si 0 cw, si 1 ccw
unsigned int count_1 = 0;
unsigned int state_out = 0;


//proto fonctions

void setup(void);
void get_pot(void);
void set_out(void);
void low_isr(void);
void high_isr(void);
int abval(int);


void main(void)
{
    setup();                                                //initialisation
    get_pot();
    LATE = 0b00000000;
    while(1)
    {
    }                                               
}

void setup (void)
{           
    /*config timers*/

    T0CON = 0b11000101;                                     // timer on, 8bits, internal clock, prescaler on + value 1/64 (152 interruptions par seconde)
                                                            // data acquisition interrup 
    T2CON = 0b00111100;                                     // output moditication loop timer 8bits 1/8postscale 1200 interrupt/second
    PR2 =   0b00001111;                                      

    /*config adc*/

    ADCON1 = 0b00001010;                                    // A0->A4 analo + VDD+GND reference
    ADCON2 = 0b10111000;                                    // A/D acq time (ADCON2) 20TAD, A/D conversion clock (ADCON2)
                                                            // right justified
    ADCON0 = 0b00000001;                                    // Turn on A/D module (ADCON0) + channel select

    /*config des pins*/

//  TRISA = 0b00011111;                                     // 5 entrées analogiques + 3 digitales
//  TRISB = 0b01001100;                                     // sorties pour la version finale
    TRISE = 0b00000000;                                     // sorties pour la version test
//  PORTA = 0b00000000;                                     // Clear A
    PORTE = 0b00000000;                                     // clear E

    /*config interruptions*/

    RCONbits.IPEN = 1;                                      // priority enabled
    INTCON  = 0b11100000;                                   // enable les interruption hautes et basses, Timer0 interrupt On 
    INTCON2 = 0b10000100;                                   // Pull up désactivés +timer0 high(acquisition vitesse) 
    PIE1bits.TMR2IE = 1;                                    // enable interrupt timer2
    IPR1bits.TMR2IP = 0;                                    // timer 2 en priorité basse(mise à jour des pins)
}


void get_pot (void)                                         //get the value of the pot and computes the data
{                                                   
    ADCON0bits.CHS1 = 0;                                    
    ADCON0bits.CHS0 = 0;
    ADCON0bits.GO = 1;                                      
    while(ADCON0bits.GO==1){}                               
    position_t1 = ADRESH*256+ADRESL;                        
    speed = position_t1 - position_t0;
    if(speed<0) direction = 1;
    else direction = 0;
    speed_abs = abval(speed);
    position_t0 = position_t1;
}

void set_out (void)                                         //set the output according the speed and direction
{
    if(speed_abs>1)
    {
        count_1++;
        if(count_1>=(1023-speed_abs)/4)                     //counter that makes the output change more or less faster
        {
            if(direction==1)
            {
                switch(state_out)
                {
                    case 0: 
                    {
                        LATE = 0b00000000;
                        state_out++;
                    }
                    break;
                    case 1:
                    {
                        LATE = 0b00000001;
                        state_out++;
                    }
                    break;
                    case 2: 
                    {
                        LATE = 0b00000011;
                        state_out++;
                    }       
                    break;
                    case 3:
                    {
                        LATE = 0b00000010;
                        state_out=0;
                    }
                    break;      
                }
            }
            else if(direction==0)
            {   
                switch(state_out)
                {
                    case 0: 
                    {
                        LATE = 0b00000000;
                        state_out=3;
                    }
                    break;
                    case 1:
                    {
                        LATE = 0b00000001;
                        state_out--;
                    }
                    break;
                    case 2: 
                    {
                        LATE = 0b00000011;
                        state_out--;
                    }       
                    break;
                    case 3:
                    {
                        LATE = 0b00000010;
                        state_out--;
                    }
                    break;      
                }
            }
            count_1=0;
        }
    }
}

int abval(int val)  
 { 
     return (val<0 ? (-val) : val);
 }

#pragma interrupt high_isr                                                      
void high_isr (void)                                        //interruption de récupération des adc
{   
    if(INTCONbits.TMR0IF==1)                                    
    {
        get_pot();
        INTCONbits.TMR0IF=0;
    }                                                       
}

#pragma interruptlow low_isr
void low_isr (void)                                         //interruption de mise à jour des sorties
{                                                       
    if(PIR1bits.TMR2IF==1)                              
    {
        set_out();
        PIR1bits.TMR2IF=0;
    }           
}   

/*
*********************************************************************************************************
 * Interupt Vectors
*********************************************************************************************************
*/
#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
    {
        _asm goto low_isr _endasm
    }


#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
    {
        _asm goto high_isr _endasm
    }

Часть комментариев кода написана на французском языке, я перевёл важные. Видите ли вы какие-либо очевидные ошибки / неправильные способы кодирования. Есть ли у вас какие-либо советы "где искать" или что смотреть?

Заранее спасибо за вашу помощь!

никола

0 ответов

Другие вопросы по тегам