新手怎么制作单片机智能小车

新手怎么制作单片机智能小车,第1张

我是一名单片机工程师,对于51单片机智能小车制作,下面的讲解你参考一下。

我看到有很多朋友想做一个属于自己的智能车,但又无从下手,今天我将详细的讲一下循迹小车的制作方法,因为所有的其它功能,都是从循迹这个扩展起来的,你把这个弄懂了,其实的功能了解一下也就懂了。

制作51单片机循迹小车,只需要四步。

1 车模。

2 主控板。

3电机驱动系统。

4 循迹传感器

下面一一进行介绍。

1车模。

对于新手来说你需要一个车模,当然也可以自己制作一个模型,下面这个是两个电机的智能小车。

上面这个车模包含有,1个车模底板,2个减速电机,2个轮子,1个万向轮(上面图片,电池盒下面那个),1个电池盒。

这种车模很多地方都有,你只要按照说明书组装成功就可以了。

2 主控板

另外你还需要一个单片机最小系统

这个主控板的单片机型号是,STC89C52RC

3 电机驱动系统。

这个电机驱动系统的模指颤燃块是L298N(上面图片,最大黑色那个)

这种驱动系统是可以同时驱动两个电机的,完全可以满足你小车的驱动动力,为什么要驱动洞祥呢?因为主控板的单片机电流太弱了,不够电流让电机运行,所以才会有电机驱动模块的产生。

上面这个图中,IN1 IN2和 IN3 IN4(在上面图片的右下角),是用来接单片机的端口(这就可以理解到,这四只脚是电机控制输入端),并且IN1 IN2是左边电机控制用的,为什么一个电机的控制,需要接两个脚呢?

一个电机接两个脚的话,电机就可以正转和反转了,运用到小车上面就是,可以实现小车的前进,后退,左转和右转,这已经满足小车运行时需要的功能。

4 循迹传感器

既然是循迹的智能车,那么你还需要循迹传感器

其实只需要两组红外线发光二极管,就可以实现我们的循迹功能了,如下图所示

从上面图片我们还可以看到,每组当中,都含有黑色红外线管和白色红外线管

我们的循迹小车,是循黑色线走的。

上面图片当中,中间的是黑色线,左右两边的是两组红外线管。

红外线检测黑线的原理。

当红外线检测的不是黑色,发射光通过障碍物能反射给接收,进行正常的发射与接收。

当红外线检测的是黑色,发射光通过黑线产生漫射,接收端就不能正常地接收到发射光,就是凭这一特点,就可以实现我们的小车循迹了,很好玩是吧,嘿嘿!对于智能小车的细节,一言二句说不了太多东西,详细的制作知识,百度上,,,请看“唯虚一凡单片机”,这个里面讲解比较全面,并且还有相应的程序。

以上就是个人分享的智能小车制作方法,希望能帮到你,你通过这个基础实验,发挥想象力,再扩展其它的小车功能,寻找更多的小车乐趣,喜欢的朋友请采纳和点赞,谢谢!

其实只有程序也没有用,要将程序和硬件接合起来才行。比如硬件里用PT0,程序里用PT1,当然不会达到预期目的。下在是上海交空粗通大学的程序。

Main.c

#include <hidef.h>/* common defines and macros */

#include <mc9s12db128.h>/族咐* derivative information */

#pragma LINK_INFO DERIVATIVE "mc9s12db128b"

#include "define.h"

#include "init.h"

// variable used in video process

volatile unsigned char image_data[ROW_MAX][LINE_MAX] // data array of picture

unsigned char black_x[ROW_MAX] // 0ne-dimensional array

unsigned char row // x-position of the array

unsigned char line // y-position of the array

unsigned int row_count // row counter

unsigned char line_sample // used to counter in AD

unsigned char row_image

unsigned char line_temp // temperary variable used in data transfer

unsigned char sample_data[LINE_MAX] // used to save one-dimension array got in

interruption

// variables below are used in speed measure

Unsigned char pulse[5] // used to save data in PA process

Unsigned char counter// temporary counter in Speed detect

Unsigned char cur_speed// current speed

short stand

short data

unsigned char curve // valve used to decide straight or turn

short Bounds(short data)

short FuzzyLogic(short stand)

/*----------------------------------------------------------------------------*\

receive_sci

\*----------------------------------------------------------------------------*/

unsigned char receive_sci(void) // receive data through sci

{ unsigned char sci_data

while(SCI0SR1_RDRF!=1)

sci_data=SCI0DRL

return sci_data

}

/*----------------------------------------------------------------------------*\

transmit_sci

\兆亏纯*----------------------------------------------------------------------------*/

void transmit_sci(unsigned char transmit_data) // send data through sci

{

while(SCI0SR1_TC!=1)

while(SCI0SR1_TDRE!=1)

SCI0DRL=transmit_data

}

/*****************************************************************************

***/

/*----------------------------------------------------------------------------*\

abs_sub

\*----------------------------------------------------------------------------*/

unsigned char abs_sub(unsigned char num1, unsigned char num2)

{ unsigned char difference

if(num1>=num2){

difference=num1-num2

}else{

difference=num2-num1

}

return difference

}

void pwm_set(unsigned int dutycycle)

{

PWMDTY1=dutycycle&0x00FF

PWMDTY0=dutycycle>>8

}

void get_black_wire(void) // used to extract black wire

{ unsigned char i

for(row=0row<ROW_MAXrow++){

for(line=LINE_MINline<LINE_MAX-3line++){

if(image_data[row][line]>image_data[row][line+3]+VALVE){

for(i=3i<10i++){

if(image_data[row][line+i]+VALVE<image_data[row][line+i+3]){

black_x[row]=line+i/2+2

i=10

}

}

line=LINE_MAX

} else{

//black_x[row]=(black_x[row]/45)*78

}

}

}

}

/*----------------------------------------------------------------------------*\

speed_control

\*----------------------------------------------------------------------------*/

void speed_control(void)

{

unsigned int sum,average

sum=0

for(row=0row<FIRST_FIVErow++){

sum=sum+black_x[row]

}

average=sum/FIRST_FIVE

curve=0

for(row=0row<FIRST_FIVErow++)

{

curve=curve+abs_sub(black_x[row],average)

if(curve>CURVE_MAX){

curve_flag=0

speed=low_speed}

else{

curve_flag=1

speed=hign_speed

}

}

}

/*----------------------------------------------------------------------------*\

steer_control

\*----------------------------------------------------------------------------*/

void steer_control(void)

{ unsigned int dutycycle

unsigned char video_center

unsigned int coefficient

int E,U//current

static int e=0

video_center=(LINE_MIN+LINE_MAX)/2

stand=abs_sub(black_x[1]+ black_x[9],2*black_x[5])

E=video_center-black_x[8]

coefficient=30+1*FuzzyLogic(stand)

U=coefficient*E

dutycycle=Bounds(center+U)

pwm_set(dutycycle)

}

// make sure it is within bounds

short Bounds(short data){

if(data>right_limit){

data = right_limit

}

if(data<left_limit){

data = left_limit

}

return data

}

Void speed_get(void)

{

Unsigned char temp

Counter++

Temp=PACN1

cur_speed=temp-pulse[counter-1]

pulse[counter-1]=temp

if(counter==5)

{

counter=0

}

}

Void set_speed(unsigned char desired_speed)

{

If(desired_speed<cur_speed)

{

PWMDTY2=low_speed

}

Else

{

PWMDTY2=high_speed

}

}

/*****************************************************************************

*\

Main

\*****************************************************************************

*/

void main(void) {

// main functiion

init_PORT()

// port initialization

init_PLL()

// setting of the PLL

init_ECT()

init_PWM()

// PWM INITIALIZATION

init_SPEED()

init_SCI()

for() {

if(field_signal==0){ // even->odd

while(field_signal==0)

row_count=0

row_image=0

EnableInterrupts

while(row_count<ROW_END){

get_black_wire()

speed_control()

steer_control()

}

DisableInterrupts

}

else{ // odd->even

while(field_signal==1)

row_count=0

row_image=0

EnableInterrupts

while(row_count<ROW_END){

get_black_wire()

speed_control()

steer_control()

}

DisableInterrupts

}

/* transmit_sci('x')

for(row=0row<ROW_MAXrow++){

transmit_sci(black_x[row])

}

transmit_sci(curve)

*/

}

}

interrupt 6 void IRQ_ISR()

{

row_count++

if((row_count>ROW_START)&&(row_count%INTERVAL==0)&&(row_image<ROW_MAX))

{

init_AD()

for(line_sample=0line_sample<LINE_MAXline_sample++){

while(!ATD0STAT1_CCF0)// WAIT FOR TRANSFORM TO END

sample_data[line_sample]=signal_in// A/D transfer

}

ATD0CTL2=0x00

row_image++

}

if((row_count>ROW_START)&&(row_count%INTERVAL==2)&&(row_image<ROW_MAX+

1)){

for(line_temp=0line_temp<LINE_MAXline_temp++){

image_data[row_image-1][line_temp]=sample_data[line_temp]

}

}

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// THE END

//

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Define.h // all macros are define in this header file

/*----------------------------------------------------------------------------*\

macro need to be used in video sample

\*----------------------------------------------------------------------------*/

////////////////////////////

#define signal_in ATD0DR0L // signal from video: right aligned mode,

// only use low 8-bit in ATD Conversion Result

Registers

#define field_signal PTT_PTT2 // field signal is sent into PortT_bit2

#define LINE_MIN 12 // first effective pint in each row

#define LINE_MAX 78 // number of points sampled in each row

#define ROW_MAX 10 // number of rows needed to be sampled in each

picture

#define ROW_START 50 // begin to sample from line start

#define ROW_END 300 // end flag of sampling

#define INTERVAL 20 // interval between effective rows

#define VALVE 24 // valve to decide black track or white track

#define FIRST_FIVE 5

/*----------------------------------------------------------------------------*\

舵机控制变量

\*----------------------------------------------------------------------------*/

#define left_limit 7400 //

#define center 6400 //

#define right_limit 5400 //

//#define coefficient 30 // (LEFT-RIGHT)/(LINE_MAX-LINE_MIN)

/*----------------------------------------------------------------------------*\

速度控制变量

\*----------------------------------------------------------------------------*/

#define curve_flag PORTE_BIT2 // indicate straight line or not

#define speed PWMDTY2 // speed of the car

#define CURVE_MAX 24 // valve to decide straight track or not

#define hign_speed 120 // speed used on straight track

#define low_speed 100 // speed used on the turn

/*----------------------------------------------------------------------------*\

define jump wirecode switchLed

\*----------------------------------------------------------------------------*/

#define JP4_1 PTT_PTT7 // JP4

#define JP4_2 PTT_PTT6

#define JP4_3 PTT_PTT5

#define JP4_4 PTT_PTT4

#define JP4_5 PTP_PTP4

#define JP4_6 PTP_PTP5

#define JP4_7 PTP_PTP6

// define code switch

#define RP1_1 PTM_PTM0

#define RP1_2 PTM_PTM1

#define RP1_3 PTM_PTM2

#define RP1_4 PTM_PTM3

#define RP1_5 PTM_PTM4

#define RP1_6 PTM_PTM5

#define RP1_7 PORTAD0_PTAD4

#define RP1_8 PORTAD0_PTAD3

// define Led

#define Led1 PORTA_BIT4

#define Led2 PORTA_BIT5

#define Led3 PORTA_BIT6

#define Led4 PORTA_BIT7

Init.c // include initial function in this file

#include <hidef.h>/* common defines and macros */

#include <mc9s12db128.h>/* derivative information */

#include "define.h" /* all macro included */

#include "init.h" /* all init function included */

#pragma LINK_INFO DERIVATIVE "mc9s12db128b"

/*----------------------------------------------------------------------------*\

init_PLL

\*----------------------------------------------------------------------------*/

void init_PLL(void)

// setting of the PLL

{

REFDV=3

SYNR=7// bus period=16Mhz*(SYNR+1)/(REFDV+1)

while(0==CRGFLG_LOCK)// wait for VCO to stablize

CLKSEL=0x80

// open PLL

}

Void init_ECT(void)

{

TIOS_IOS3=0// set PT3 as input capture

TCTL4=0b11000000// set pt3 as any edge triggered

ICPAR_PA1EN=1// PA1 enabled

}

/*----------------------------------------------------------------------------*\

init_PORT

\*----------------------------------------------------------------------------*/

void init_PORT(void) // port initialization

{

DDRT_DDRT2=0

// Port M1 function as even-odd field signal

input

DDRJ_DDRJ6=1

// Port J6 enable 33886 0 enable

// Led port

DDRA_BIT4 =1

DDRA_BIT5 =1

DDRA_BIT6 =1

DDRA_BIT7 =1

INTCR_IRQE =1// IRQ Select Edge Sensitive Only

INTCR_IRQEN=1// External IRQ Enable

//输出指示 JP4_1 PTT_PTT0

DDRT_DDRT7=1

DDRT_DDRT6=1

DDRT_DDRT5=1

DDRT_DDRT4=1

DDRP_DDRP4=1//PTP_PTP0

DDRP_DDRP5=1

DDRP_DDRP7=1

}

/*----------------------------------------------------------------------------*\

init_AD

\*----------------------------------------------------------------------------*/

void init_AD(void)

// initialize AD

{

ATD0CTL2=0xC0

// open AD, quick clear, no wait mode, inhibit outer awake, inhibit interrupt

ATD0CTL3=0x08

// one transform in one sequence, No FIFO, contine to transform under freeze mode

ATD0CTL4=0x81

// 8-bit precision, two clocks, ATDClock=[BusClock*0.5]/[PRS+1] PRS=1, divider=4

BusClock=8MHZ

ATD0CTL5=0xA0// right-algned unsigned,single channel,

channel 0

ATD0DIEN=0x00// inhibit digital input

}

/*----------------------------------------------------------------------------*\

init_PWM

\*----------------------------------------------------------------------------*/

void init_PWM(void)

// PWM initialize

{

PTJ_PTJ6 = 0 // "0" enable 33886 motor, "1" disable it

PWME = 0x00 // PWW is disabled

PWMCTL_CON01 = 1 // combine PWM0,1

PWMPRCLK = 0x33 // A=B=32M/8=4M

PWMSCLA = 100 // SA=A/2/100=20k

PWMSCLB = 1 // SB=B/2/1 =2000k

PWMCLK = 0b00011100// PWM0,1-APWM2,3-SBPWM4-SA

PWMPOL = 0xff // Duty=High Time

PWMCAE = 0x00 // left-aligned

PWMPER0 = 0x4e

PWMPER1 = 0x20

// 20000 = 0x4e20Frequency=A/20000=200Hz

PWMDTY0 = 0x18

PWMDTY1 = 0x6a // initialize PWM

PWME_PWME1 = 1 // enable steer

PWMDTY2 = 20 // Duty cycle

PWMPER2 = 200 // Frequency=SB/200=10K

PWME_PWME2 = 1 // enable motor

}

/*----------------------------------------------------------------------------*\

init_SPEED

\*----------------------------------------------------------------------------*/

void init_SPEED(void) {

DDRM_DDRM0 =0 //code switch 1 on RP1

DDRM_DDRM1 =0 //code switch 1 on RP1

DDRM_DDRM2 =0 //code switch 1 on RP1

DDRM_DDRM3 =0 //code switch 1 on RP1

DDRM_DDRM4 =0 //code switch 1 on RP1

DDRM_DDRM5 =0 //code switch 1 on RP1

ATD0DIEN_IEN4 = 1//code switch 1 on RP1,Enable Digital Input PAD4

ATD0DIEN_IEN3 = 1//code switch 1 on RP1,Enable Digital Input PAD3

if(RP1_1==1) {

speed= hign_speed +2*(RP1_2*10+RP1_3*5+RP1_4*2+RP1_5*2+RP1_6+RP1_7+RP1_8)

}

else{

speed= hign_speed -2*(RP1_2*10+RP1_3*5+RP1_4*2+RP1_5*2+RP1_6+RP1_7+RP1_8)

}

}

/*****************************************************************************

***/

/*----------------------------------------------------------------------------*\

init_SCI

\*----------------------------------------------------------------------------*/

void init_SCI(void) // initialize SCI

{

SCI0BD = 104 // bode rate=32M/(16*SCI0BD)=19200

SCI0CR1=0x00 //

SCI0CR2=0b00001100

}

Init.h

void init_PLL(void)

void init_AD(void)

void init_PWM(void)

void init_SPEED(void)

void init_SCI(void)

void init_PORT(void)

Void init_ECT(void)

Fuzzy.asm // S12 fuzzy logic code

RAM: section

Fuzzy Membership sets

input membership variables

absentry fuzvar

fuzvar: ds.b 5 inputs

Z: equ 0 indicate of straight line

VS: equ 1 turn slightly

S: equ 2 turn a little

BB: equ 3 a big turn

VB: equ 4 a very big turn

output membership variables

absentry fuzout

fuzout: ds.b 4 outputs

remain: equ 5 no change on kp

little: equ 6 little change on kp

big: equ 7 big change on Kp

very_big: equ 8 very big change on kp

EEPROM: section

fuzzification

s_tab: dc.b 0,35,0,8 indicate of straight line

dc.b 0,69,8,8 turn slightly

dc.b 35,104,8,8 turn a little

dc.b 69,138,8,8 a big turn

dc.b 104,255,8,0 a very big turn

rules:

constructing of rule

dc.b Z, $FE,remain,$FE

dc.b VS, $FE,little,$FE

dc.b S, $FE,big,$FE

dc.b BB, $FE,big,$FE

dc.b VB, $FE,very_big,$FE

dc.b $FF end of the rule

addsingleton:

dc.b 0,1,2,3 setting of the weight

absentry FuzzyLogic

FuzzyLogic:

pshx

ldx #s_tab

ldy #fuzvar

mem number of mem indicates the number of input

mem

mem

mem

mem

ldab #4 number of output fuzzy membership sets

cloop:

clr 1,y+ clear output fuzzy variables

dbne b,cloop

ldx #rules

ldy #fuzvar

ldaa #$FF

rev

ldy #fuzout

ldx #addsingleton

ldab #4

wav

ediv

tfr y,d return dpower

pulx

rts

你在中断里面把flag=1进入主指老烂函数后flag一直保持1,而你中断的判断条件是if(flag==0&&P32==0),它就进不了中断了。你要想这么写的话可以改成这样含芹看看:

void INT_0() interrupt 0

{

flag==0;

if(flag==0)

{

P2=0x00 //小车停车

delayms(2000) //延时两秒

flag=1

}

}

或者干脆把if判断去了得了,(仅代表自己看法,我也不怎么唯漏懂啊)。自己多调试调试,肯定能做好的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12343475.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存