我目前正在以实习生的身份研究机器人,并且必须为电机选择替换驱动器。轴的位置信息由模拟电位器给出。我确实有 3 个由 technosoft 提供的驱动程序,它们需要旋转编码器(正交)信息来完成他们的调节工作。我正在考虑将此模拟信号转换为正确的正交信号以使其工作。
我设计它的方式是 pic18 以 150hz 对电位器值进行采样,将前一个值减去当前值以了解速度(一种推导)。它产生一个速度的绝对值和一个方向信号,这些信号通过正交编码器的 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
}
部分代码注释是法语的,我翻译了重要的。您是否看到任何明显的错误/错误的编码方式。您对“在哪里搜索”或看什么有什么建议吗?
提前感谢您的帮助!
尼古拉斯