搜索
bottom↓
回复: 11

平衡车高手高手请进

[复制链接]

出0入0汤圆

发表于 2011-5-14 01:26:35 | 显示全部楼层 |阅读模式
现在正在搞平衡车,遇到了一些问题,请高手给讲解一下,谢谢

以下是程序,源自Elektor-Wheelie
但传感器我选用了ma7260 和 ewts84

5v参考电压

程序里有一些读不懂的地方如下面加**********段落。里面的35是如何得来的


还有Sub Algo函数也不理解其中17是表示什么?


应为在另一个开源项目中也看到相应的程序,但数值不同。

看了一些关于互不滤波的文章,Motor Output = Kp × (Angle) + Kd × (Angular Velocity),但这里的Kp Kd 应该相加是1才对,为什么程序里不是。


修改相应参数后小车变化不大,依然抖动,不能平衡。


里面的竹市是我加上的,不知对否。




'---------------------------------------------------------------------------
'  _____ _     _   _              _ _ _ _           _ _
' |   __| |___| |_| |_ ___ ___   | | | | |_ ___ ___| |_|___
' |   __| | -_| '_|  _| . |  _|  | | | |   | -_| -_| | | -_|
' |_____|_|___|_,_|_| |___|_|    |_____|_|_|___|___|_|_|___|
'
' (c)2009 Elektor International Media B.V.
'---------------------------------------------------------------------------
'Version: EWOF100 - Elektor Wheelie Open Firmware 1.0.0
'---------------------------------------------------------------------------
'Purpose:
'  Elektor-Wheelie motor control source code
'---------------------------------------------------------------------------
'Description:
'  On power on the LEDs are flashing in the order green-yellow-red
'  If initialization fails the red LED is blinking and the Wheelie is blocked.
'  Blinking 2 times = gyro failure, 3 times = adxl failure.
'  If initialization has been successful the 3 LEDs show the battery status:
'  green = battery full, yellow = battery empty and red = battery dead.
'---------------------------------------------------------------------------
'Older sources:
'  FW 2.6: Original Elekor firmware version 2.6 by Chris Krohne 2009
'  Beta versions by G黱ter Gerold 2009
'     beta.0:
'        Parts with assembler code deleted;
'        interrupts changed;
'        overflows fixed;
'        fixed bug at foot switch;
'        code part MMode changed;
'        code part PWM changed;
'        unused variables deleted;
'        unused constants deleted.
'     beta.1:
'        Code for telemetric purposes added (for LCD and PC-connection).
'     beta.2:
'        Faster control loop for better balance at inclination changes;
'        new sensor calibration for every start (foot switch action);
'        softer filter parameters.
'     beta.3:
'        Unused pins as inputs with pull-ups;
'        no more speed measurement, because there is no real speed measure.
'     beta.4:
'        More comments;
'        fixed bug with LEDs (red LED);
'        changed order of code.
'---------------------------------------------------------------------------
'Changes Log:
'  EWOF100: version 1.0.0
'     Starting point for improvements by the community. Equivalent to beta.4.
'---------------------------------------------------------------------------
'To do:
'  Improvement of steering control.
'  Integration of real speed info.
'  Implementation of a "security slow down mode".
'  Etc.
'---------------------------------------------------------------------------
'Contact:
'  Please post ideas, improvements and code into this thread in the Elektor forum:
'  http://www.elektor.de/forum/foren-ubersicht/foren-zu-elektor-projekten/elektorwheelie/elektor-wheelie-open-firmware.1131470.lynkx
'  G黱ter Gerold: tv@gerold-online.de
'---------------------------------------------------------------------------

$crystal = 16000000
$baud = 19200
$regfile = "m16def.dat"
$hwstack = 100                                              'Hardware stack
$swstack = 100                                              'Software stack
$framesize = 100                                            'Frame space
'设置输出端口
Pwm_al Alias Ocr1al
Pwm_bl Alias Ocr1bl
Led3 Alias Portc.3
Led2 Alias Portc.2
Led1 Alias Portc.1
Buzz Alias Portc.0
Cw_ccw_a Alias Portd.7
Cw_ccw_b Alias Portd.6
' 配置看门狗32ms
Config Watchdog = 32

Config Porta = Input
Config Portb = Input
Config Portc = Output
Config Portd = Output

'AD转换一次使用13个系统时钟,预分频128,则一次AD转换花费13*1/(1600000/128)=104us
'设置ADC参数,参考电压外部供给
Config Adc = Single , Prescaler = 128 , Reference = Off
Start Adc
'8bit T0ji计时器搐发中断服务程序,每16.32ms溢出 ,为了加速中断响应时间t0设置为100,计时器从100~255. 计算得155 x 1024 x 62,5 ns = 10 ms
'Timer0 as a 8 bit timer triggers interrupt service routine On timer0 every 16,32ms (on overflow).
'To speed up the interrupt intervall Timer0 is preset to 100. Now counting from 100 to 255.
'=> Calcutulation: 155 x 1024 x 62,5 ns = 10 ms
Config Timer0 = Timer , Prescale = 1024
On Timer0 Ontimer0
'T1用于产生前进和后退的PWM脉冲,其中一个是反转
'Timer1 is used to generate both PWM signals (backward and forward).
'One of them is inverted.
Tccr1a = &B10110001                                         '8位相位修正PWM
Tccr1b = 2
Ocr1al = 255

Dim Ad_adxl As Long
Dim Ad_gyro As Long
Dim Ad_batt As Integer
Dim Ad_swi As Integer
Dim Total_adxl_gyro As Long
Dim Average_gyro As Long
Dim Average_batt As Long
Dim Drivea As Integer
Dim Driveb As Integer
Dim Buf1 As Long
Dim Buf As Long
Dim Buf2 As Long
Dim Tilt_angle As Long
Dim Drive_a As Integer
Dim Drive_b As Integer
Dim Drivespeed As Long
Dim Steeringsignal As Long
Dim Anglecorrection As Long
Dim Angle_rate As Long
Dim Balance_moment As Long
Dim Mmode As Byte
Dim Drive_sum As Long
Dim Ad_rocker As Integer
Dim Timeout As Long
Dim Rockersq As Long
Dim Rocker_zero As Integer
Dim Adxl_zero As Word
Dim Gyro_zero As Word
Dim Errno As Byte
Dim Adxl_offset As Integer

Const Mdrivesumlimit = 20000
Const Total_looptime = 300                                  ' Looptime for filters
Const Total_looptime10 = 30                                 ' Looptime for filters
Const _run = 1
Const _standby = 0
Const _down = 3
Const Sw_down = 50                                          'Thershold for foot switch
Const Critical = 80                                         'Time from releasing the foot switch until begin to stop the Wheelie    从释放脚踏开关到停车的时间
Const Max_pwm = 180                                         'Maximum motor power
Const Mmax_pwm = -180                                       'Maximum motor power
Const Battdead = 960 * Total_looptime
Const Battok = 1020 * Total_looptime

Declare Sub Get_tilt_angle
Declare Sub Set_pwm
Declare Sub Algo
Declare Sub Process
Declare Sub Checkbatt
Declare Sub Err_value
Declare Sub Init
Declare Sub Steering

Pwm_al = 255
Pwm_bl = 0
Average_batt = Battok
Mmode = _standby

'LEDshow on start
Set Led1
Waitms 150
Set Led2
Waitms 150
Set Led3
Set Buzz
Waitms 250
Reset Led1
Reset Led2
Reset Led3
Reset Buzz

'---------------------------------------------------------------------------
'Checking foot switch:
'  When the Wheelie is switched on the foot switch should be closed (not pressed down).
'  Otherwise the Wheelie would start. Therefore the foot switch is read 10 times
'  and the mean of this values is compared with a threshold of 100.
'  If this mean is smaller than all is okay. Otherwise an error occurs..
'---------------------------------------------------------------------------
Ad_swi = 0
For Buf = 1 To 10                                           'Calculate mean out of 10 measurements
  Ad_swi = Ad_swi + Getadc(4)
  Waitms 1
Next Buf
Ad_swi = Ad_swi / 10
Waitms 2

If Ad_swi < 100 Then                                        'If foot switch is pressed: error
  Errno = 4
  Goto Err_value
End If
'Print Ad_swi
Gosub Init
Enable Interrupts
Enable Timer0

'---------------------------------------------------------------------------
'Main Loop:
'  The right space for extending with code.
'---------------------------------------------------------------------------
Do
  'Do nothing (until now)s
Loop

'---------------------------------------------------------------------------
'Ontimer0:
'  This service routine contains control logic and is started every 10ms.
'  Exact time: 1/16 MHz * 1024 * (255-100) = 9,92 ms
'---------------------------------------------------------------------------
Ontimer0:
  Reset Watchdog
  Timer0 = 100
  Gosub Get_tilt_angle
  Gosub Algo
  Gosub Steering
  Gosub Set_pwm
  Gosub Checkbatt
  Gosub Process
Return

'---------------------------------------------------------------------------
'Get_tilt_angle:
'  Measurement of all analog values (5 values).
'  Using 104 祍 per measurement total time is 520 祍.
'  The values are used to build moving averages.
'---------------------------------------------------------------------------
Sub Get_tilt_angle
  Ad_gyro = Getadc(2)
  'Ad_gyro = 1024 - Ad_gyro                                  'Inverted value for Ad_gyro
'   Ad_gyro = Ad_gyro
  Ad_adxl = Getadc(1)
'  Ad_adxl = 1024 - Ad_adxl
  Ad_batt = Getadc(6)
  Ad_rocker = Getadc(5)
  Ad_swi = 1024 - Getadc(4)                                 'Inverted value for Ad_swi

  'Subtract   1/300th   of   the   value
  Buf = Total_adxl_gyro / Total_looptime
  Total_adxl_gyro = Total_adxl_gyro - Buf

  'Filter for ADXL
  Buf = Ad_adxl - Adxl_zero                                 'Deviation from horizontal position
  Buf = Buf + Adxl_offset                                   'Ideal value for Adxl_offset would be zero
  Total_adxl_gyro = Total_adxl_gyro + Buf                   'A new 1/300th value is added

  'Filter for gyro
  Buf1 = Average_gyro / Total_looptime
  Average_gyro = Average_gyro - Buf1                        'Subtract 1/300th of the value
  Average_gyro = Average_gyro + Ad_gyro                     'A new 1/300th value is added

  Buf1 = Average_gyro / Total_looptime10                    'Calculation of  angular rate

****************************************************************************************************************
  Buf = Ad_gyro * 10
  Buf1 = Buf1 - Buf                                         'Deviation from zero
  Buf1 = Buf1 * 35
  Buf1 = Buf1 / 100                                         '3.5 * deviation rate
  Angle_rate = Buf1                                         'with moving average over 300 measurements

  'Calculation of Tilt_angle
  'Subtract the contained part of Gyro?
  'A bit unclear...
  Buf1 = Angle_rate * 1
  Total_adxl_gyro = Total_adxl_gyro + Buf1
  Tilt_angle = Total_adxl_gyro / Total_looptime10
End Sub
******************************************************************************************************************
'---------------------------------------------------------------------------
'Algo:
'  Calculation of motor current out of sensor values.
'---------------------------------------------------------------------------
Sub Algo                                                    '算法
  Buf = Tilt_angle
  Buf = Buf * 17                                             '倾斜角度
  Buf1 = Angle_rate * 17                                    '加速率
  Balance_moment = Buf1 + Buf                               '平衡时刻
  Drive_sum = Drive_sum + Balance_moment                    '驱动量=先前值+平衡时刻
     If Drive_sum > 55000 Then                              'Limiting Drive_sum
     Drive_sum = 55000
  End If
  If Drive_sum < -55000 Then                                'Limiting Drive_sum
     Drive_sum = -55000
  End If
  Buf = Drive_sum / 155
  Buf1 = Balance_moment / 165
  Drivespeed = Buf + Buf1                                   '驱动速度


End Sub

'---------------------------------------------------------------------------
'Steering:
'  Calculation of steering values.
'---------------------------------------------------------------------------
Sub Steering
  Rockersq = Rocker_zero - Ad_rocker
  Buf1 = Drive_sum / 20000
  'Print "rocker" ; Rocker_zero ; Ad_rocker                  'Steering depends on speed
  Buf1 = Abs(buf1)
  If Buf1 < 1 Then Buf1 = 1
  Rockersq = Rockersq / Buf1
  'Some safety lines, limits steering: Drive_sum 55000 max = +-5   Buf1 = Drive_sum / 2000
  Buf1 = Abs(buf1)
  If Buf1 > 22 Then Buf1 = 22
  Buf1 = 27 - Buf1
  Buf2 = Buf1 * -1
  If Rockersq > Buf1 Then Rockersq = Buf1
  If Rockersq < Buf2 Then Rockersq = Buf2
  Steeringsignal = Rockersq
  Drive_a = Drivespeed - Steeringsignal
  Drive_b = Drivespeed + Steeringsignal
End Sub

'---------------------------------------------------------------------------
'Set_pwm:
'  Limiting PWM and set direction flags.
'---------------------------------------------------------------------------
Sub Set_pwm
  'Limiting PWM                          '限制速度
  If Drive_a > Max_pwm Then
     Drive_a = Max_pwm
  Elseif Drive_a < Mmax_pwm Then
     Drive_a = Mmax_pwm
  End If
  If Drive_b > Max_pwm Then
     Drive_b = Max_pwm
  Elseif Drive_b < Mmax_pwm Then
     Drive_b = Mmax_pwm
  End If

  'Set direction flag              '设置 方向标志
  If Drive_a < 0 Then
     Cw_ccw_a = 1
  Else
     Cw_ccw_a = 0
  End If
  If Drive_b < 0 Then
     Cw_ccw_b = 1
  Else
     Cw_ccw_b = 0
  End If

  Drivea = Abs(drive_a)                                     '返回绝对值速度
  Driveb = Abs(drive_b)
  'Print "dribca=" ; Drivea ; "dribcb=" ; Driveb ;
  'Inverse signal with 180?phaseshift to PWMb
  Pwm_al = 255 - Drivea                                     '180度换向
  Pwm_bl = Driveb
End Sub

'---------------------------------------------------------------------------
'CheckBatt:    电池检测
'  Battery state (voltage) is signaled with the 3 LEDs.
'---------------------------------------------------------------------------
Sub Checkbatt
  'Moving average of battery voltage
  Buf1 = Average_batt / Total_looptime
  Average_batt = Average_batt - Buf1
  Average_batt = Average_batt + Ad_batt

  'Set the right LED
  If Average_batt > Battok Then
     Set Led1
     Reset Led2
     Reset Led3
  End If
  If Average_batt < Battok Then
     Set Led2
     Reset Led3
     Reset Led1
  End If
  If Average_batt < Battdead Then
     Reset Led2
     Reset Led1
     Set Led3
  End If
End Sub

'---------------------------------------------------------------------------
'Process:
'  Processing Wheelie states.
'---------------------------------------------------------------------------
Sub Process
  Select Case Mmode
  Case _standby                                             'Foot switch is released:wating...  脚踏开关释放则等待
     Drive_a = 0
     Drive_b = 0
     Drivespeed = 0
     Anglecorrection = 0
     Drive_sum = 0
     Total_adxl_gyro = 0
     Tilt_angle = 0
     Timeout = 0
     If Ad_swi > Sw_down Then                               'If foot switch is pressed: change Mmode to run
        Gosub Init                                          'Initialize sensors  脚踏开关压下则进入运行模式初始化传感器
           Mmode = _run
           Timeout = 0
        End If
  Case _run                                                 'Foot switch is pressed: action...    脚踏开关压下:运行
     If Ad_swi < Sw_down Then                               'If foot switch is released long enough: change Mmode to down 如果被释放时间过长则进入减速模式
        Incr Timeout
        If Timeout > Critical Then
           Mmode = _down
           Timeout = 0
        End If
     Else
        Timeout = 0
     End If
  Case _down                                                'Motors slowdown slowly      减速
     Stop Watchdog
     For Buf1 = 1 To 255
        If Drive_a = 0 And Drive_b = 0 Then
           Exit For
        End If
        If Drive_a > 0 Then
           Decr Drive_a
        End If
        If Drive_a < 0 Then
           Incr Drive_a
        End If
        If Drive_b > 0 Then
           Decr Drive_b
        End If
        If Drive_b < 0 Then
           Incr Drive_b
        End If
        Waitms 25                                           'Loop speed
        Gosub Set_pwm
        Next Buf1
     Mmode = _standby
     Start Watchdog
  Case Else                                                 'If an unknown state occurs then slow down如果一个未知状态发生则减速
     Mmode = _down
  End Select
End Sub

'---------------------------------------------------------------------------
'Init:
'  Calibration: Calculation of steering mid and platform horizontal position.
'---------------------------------------------------------------------------
Sub Init
  'Calculate mid position of steering (Steering_zero) 计算方向中值
  Stop Watchdog
  Ad_rocker = 0
  For Buf = 1 To 10                                         'Mean out of 10 values
     Ad_rocker = Ad_rocker + Getadc(5)
     Waitms 1
  Next Buf
  Rocker_zero = Ad_rocker / 10
   'Print Rocker_zero ; "  ";
  'Calculate gyro horizontal position of platform计算陀螺仪平台水平位置
  Ad_gyro = 0
  For Buf = 1 To 100                                        'Mean out of 100 values
     Buf1 = Getadc(2)
  '   Buf1 =  Buf1
     Ad_gyro = Ad_gyro + Buf1
     Waitms 2
  Next Buf
  Gyro_zero = Ad_gyro / 100
  Average_gyro = Total_looptime * Gyro_zero                 'Preset Average_gyro
    'Print Gyro_zero ; "  ";
  'Calculate ADXL horizontal position of platform计算加速计平台水平位置
  Ad_adxl = 0
  For Buf = 1 To 100                                        'Mean out of 100 values
     Buf1 = Getadc(1)
     Ad_adxl = Ad_adxl + Buf1
     Waitms 2
  Next Buf
  Adxl_zero = Ad_adxl / 100
     'Print Adxl_zero ; "  ";
  'Check if values are in tolerable range     检查陀螺仪/加速计值是否在允许范围内
  Start Watchdog
  If Adxl_zero < 300 Then
     Errno = 3
     Goto Err_value
  End If
  If Adxl_zero > 600 Then
     Errno = 3
     Goto Err_value
  End If
  If Gyro_zero < 350 Then
     Errno = 2
     Goto Err_value
  End If
  If Gyro_zero > 750 Then
     Errno = 2
     Goto Err_value
  End If
End Sub

'---------------------------------------------------------------------------
'Err_value:
'  On error the program processes this routine endlessly.
'  Switch the Wheelie off to reset.
'---------------------------------------------------------------------------
Sub Err_value
  Stop Watchdog
  Do
  'Print "eror=" ; Errno
     For Buf = 1 To Errno
        Set Led3
        Waitms 350
        Reset Led3
        Waitms 350
     Next Buf
     Wait 2
  Loop
End Sub

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2011-5-14 09:21:22 | 显示全部楼层
自己顶一下

出0入0汤圆

发表于 2011-5-14 11:22:30 | 显示全部楼层
用VB编的?

出0入0汤圆

 楼主| 发表于 2011-5-14 16:35:39 | 显示全部楼层
是的,德国人的,感觉简单实用就行。

有专门的论坛,但都是鸟语看不懂。

高手能帮看看吗?

出0入0汤圆

 楼主| 发表于 2011-5-14 21:54:44 | 显示全部楼层
没人能回答吗?

出0入0汤圆

 楼主| 发表于 2011-5-15 11:22:50 | 显示全部楼层

出0入0汤圆

 楼主| 发表于 2011-6-1 21:51:05 | 显示全部楼层
定,木有人回答吗?

出0入0汤圆

发表于 2011-7-30 19:01:00 | 显示全部楼层
高手没在,我也想做,正在学习单片机,希望看到高手支持。

出0入0汤圆

发表于 2012-7-10 17:13:52 | 显示全部楼层
这个是VB?不应该是单片机控制的吗?

出0入0汤圆

发表于 2012-7-17 14:37:37 | 显示全部楼层
17可能是系数。有的版本是19.

出0入0汤圆

发表于 2012-7-17 22:34:04 | 显示全部楼层
  零点不固定。另外可能    Sub Get_tilt_angle   有错。用示波器发现  Ad_adxl 变化时。pwm  没变化。

出0入0汤圆

 楼主| 发表于 2012-9-13 10:41:00 | 显示全部楼层
楼上也在研究,是不是老外的程序没有完全提供正确的版本,
不妨将你的研究心得与大家分享一下。
感觉老外的程序比较简单。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-17 06:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表