地心一號-基於STM8的超迷你自平衡小車-DIY套件

大家好,我是起航,我又來了,這次跟大家聊聊平衡小車。瞭解我的朋友都知道,我極有可能會把帖子寫的又臭又長,所以,,,做好準備,上車吧!

先說項目初衷:想給我外甥做個玩具。

是的,就這麼簡單。但是做的時候發現,呵呵~~~

外甥是2010年11月份生的,現在上小學了。萌生這個想法的時候是2016年,那時做爲一名電子工程師經常在我姐面前吹牛,說我有多厲害。

我姐說,你給我做個空調吧,家裏缺個空調!  我............

然後我覺得,在小朋友面前顯擺一下自己有多厲害還是可以的。所以,想了想做什麼合適。其實,可選項也沒幾個。我總不能給外甥做個流水燈、MP3、電子秤吧。

四軸飛行器目前不行,因爲有螺旋槳,非常容易傷到小朋友。所以,小車是首選。當然,四個軲轆的就算了,沒什麼意思。要做就做兩輪,這樣纔有成就感。

確定做什麼了,然後就是收集相關資料。我把網上能搜到的大部分自平衡小車資料都下載,過了一遍,這是基本功課,必須要做好。

看完才知道,兩輪自平衡車,最開始是給雙腿行動不變的人設計的。但是,發明出來以後,發現它在保安、巡邏等方面作用更加明顯,於是就慢慢普及開了。

國內早期的自平衡小車的方案我找到的是阿莫電子論壇的一篇帖子,2010年的,很牛逼。方案如下:

控制器:ATmega16;8MHz;
         加速度傳感器:MMA2260;陀螺儀:EWTS82;
         傳感器的融合:卡爾曼濾波;
         馬達:EN_2342CR(速比64)+雙路12脈衝編碼器+CD40106對信號整形;
         驅動板芯片:CD4001+IR2111+IRF1404(驅動電流可以很大);

 

還有圖片:

注意看他的控制器和傳感器,和現在的完全不一樣。

那個時候AVR單片機還是很火的。他用了ATmega16,注意頻率,只有8MHZ。然後是傳感器:一個加速度傳感器,一個陀螺儀!那個時候MPU6050貌似還沒露面(我也不知道是還沒被設計出來,還是沒推廣開,知道的可以科普下),爲了獲取加速度和角度,用了兩個傳感器。所以現在的我們還是很幸福的。

那個帖子雖然老,但是討論了很多非常有價值的問題,有興趣的同學可以百度:

自己做的雙輪自平衡小車

鏈接就不放了,度娘不穩定。

 

時間當時是2016年,網上大部分的方案是STM32+MPU6050,也有一些用arduino做的。Arduino的問題我稍後再說,當時想的是:隨大流!既然32的案例多,那麼資料就多,出於穩妥,先買個樣機玩玩吧。

當時沒認真對比,隨便買了個。買回來才發現,資料少的可憐。店鋪名稱我就不說了,這裏奉勸大家,無論買什麼,多諮詢,多對比。否則學不好,不要怪別人。樣子如圖:

外形還是很霸氣的,大小跟我的一隻鞋差不多大,電機扭矩也很給力。但是依然彌補不了賣家配套資料不足的短板。

資料少是一方面,讓我驚掉下巴的是,程序居然是用STM32的2.0的庫寫的。沒經歷過STM32庫函數版本變動的同學是不會理解的,32的庫從剛出來到現在相對穩定的3.5版本,變更了幾次,每次都是大變樣。早期的工程師叫苦不迭,甚至還有的揚言說要自己寫一套庫函數。

但當時是2016年,16年啊!!!3.5版本已經穩定好幾年了!但是賣家提供的程序竟然是2.0版本的庫函數,當然,功能是沒有問題的。所以我早期的工作就是把整套程序用3.5的庫重寫一遍,既熟悉了程序流程,也方便了後續的調試。

資料少我忍了,又讓我發現一個問題,賣家的原理圖和實際硬件不配套。我耐着性子跟賣家反映了這個問題,給出的答覆是:技術保密,不影響應用。

我再忍。

然後又發現一個問題,這個電路沒有留JTAG或者SW接口,只有一個串口下載的接口。注意,連排針上都沒有調試接口,可想而知,這個板子設計的有多失敗。

到這裏,我竟然已經習慣了。也無所謂了,於是就開始改程序改着玩。

前面我在把庫函數版本從2.0變到3.5的時候,已經過了一遍流程。所以每段程序的功能我幾乎都瞭解了,這套板子是STM32+MPU6050,然後使用6050內部DMP固件的方式來獲取角度。這種方式獲取的值的精度是很高的,而且不需要再經過濾波。但是同樣的,對單片機的ROM和RAM的要求也很高。換句話說,低配的單片機玩不來!

先改哪?

就從呼聲最高的PID參數開始吧。關於PID參數整定的文章,網上一搜一大堆。同樣,抱怨參數不好調的文章也是一大堆。那我就改參數改着玩吧。

結果發現,無論怎麼改(只要變動不是特別誇張),,,,,貌似小車都很穩定,這........和我預想的不太一樣啊......

這個問題曾經困擾了我很長一段時間,直到搜了一堆相關資料又看了稚暉的文章,才解決了我的疑惑。稚暉是誰?後面再說,同樣,會提到他的蛋黃,一個萌翻了的自平衡小車。

 

簡單來說,平衡車好不好調,有幾個因素影響:

  1. 處理器性能,DMP固件的方式肯定是很好的,32沒問題,但是一些低端單片機就玩不來了。這時,就需要讀取原始數據,然後做一階濾波或者卡爾曼濾波,這種方式來實現。
  2. 電機性能,非常重要!!!力矩越大越好。參數整定,說是P+I+D三個,但如果電機性能好,只要P+D就夠了,不需要I。現在市面上的大部分平衡車套件幾乎也不需要I,畢竟加了一個參數,難度會上去很多。
  3. 編碼器精度。電機性能好,只能保證角度平衡,但是會朝某個方向一直跑,越跑越快,最後速度跟不上,倒下。編碼器可以檢測電機轉了多少,不是轉多少圈,是一圈的幾分之幾。精度高的編碼器可以檢測電機轉了幾百分之一 圈,精度低的編碼器只能測 十幾分之一 圈,甚至幾分之一。

 

上面三點,是從硬件的角度來說的。當然,還有一些別的因素,比如說結構上,重心越低越好,體積越大越好調等。歡迎大家補充。

 

也就是說,電機性能不錯,單片機性能也高,所以PID參數調節難度不大。這就尷尬了,我都做好百米衝刺的準備了,結果告訴我已經到終點了....

既然這樣,那就換個玩法。現在的角度獲取不是DMP方式嗎? 我不用了,換成直接讀取原始數據,然後一階濾波。

先說可行性,這個思路的可行性是沒有問題的。網上普遍的反應是這個方式簡單,雖然數據不是特別準,但是做小車沒問題。我曾經在極客工坊論壇潛水很長一段時間,看了很多案例,這種原始數據+一階濾波算是比較常見的。

但是有一點,極客工坊裏大部分都是arduino,而arduino的晶體一般都是16MHZ,爲了確保我和他們儘量處於同一起跑線,我把STM32的頻率也降到了16MHZ。然後,噩夢開始了......

代碼如下:
void Yijielvbo(float angle_m, float gyro_m)
{
  float dt = 0.0f;
        dt = (float)TIM_GetCounter(TIM1);
        dt = dt / 1000000;
        TIM_SetCounter(TIM1, 0);
        angel = K1 * angle_m+ (1-K1) * (angel + gyro_m * dt);
}

         dt是每次獲取角度的時間間隔。使用這種方式,給我最大的感覺就是嚴重的滯後性。參數K1和滯後性相關,我也進行了調試,有效果,但是達不到要求。
         小車放在地上,能明顯感覺到已經向一個方向偏了一段時間了,才反映過來。如果不使用一階濾波也不用卡爾曼,可以感覺到小車的反映速度明顯快很多(當然了,還是站不起來~~~)
         所以,我當時主要疑惑的問題:一階濾波的滯後性怎麼處理,是否和電機性能有關?

現在回想起來,有兩個可能因素:1、STM32頻率從72降到16MHZ的時候,IIC的速度可能忘了調節了;2、一階濾波的代碼可能沒調好。

 

一階濾波的方式當時試了好幾天,最後忍不了了。換卡爾曼濾波吧!

這裏要說一下,賣家發貨時提供的程序只有一份讀取DMP方式的,沒有一階濾波、也沒有卡爾曼。跟賣家軟磨硬泡了一下午,給我找來了一份卡爾曼的,電機驅動方向有點問題,PID參數也需要調整。
         於是我拿過來,整了一下,在16MHZ的情況下,竟然就佔了起來。

卡爾曼,你是個好人!

 

到這裏,角度獲取的幾種方式,我都已經過了一遍了。優缺點,心裏也有數了。接下來,做點什麼?(原諒我自己玩的比較嗨,快忘了給外甥做玩具的事了)

 

我想把程序簡化一下,看看能簡化到什麼程度,於是開始了給這套程序瘦身。不瘦不知道,一瘦發現賣家的程序裏很多沒用的東西(我竟然已經習慣了這種賣家,沒有情緒撥動了),於是我都逐步測試,確認沒用,然後刪了。

簡化之前,下載到單片機裏面要佔用30多K,簡化以後,我印象裏只有15K左右了。如果使用寄存器方式編程的話,代碼量還要小一些。

 

到這裏,我已經清楚要給外甥做一個什麼樣的玩具了。這個玩具不只是給他的,也是給我自己的。

硬件電路框架還是網上普遍在用的,但是核心我已經不想用STM32了,因爲沒有意思。我想用STM8,因爲做這個東西,8位單片機足夠了。

 

這也是我做這個東西,強烈想表達的一個想法。有一段時間,我在QQ羣裏和網友交流技術問題的時候,經常會有一些新人提問:學8位單片機好,還是學STM32好?

爲什麼他們會問這樣的問題?

因爲32位單片機的各方面性能幾乎都是碾壓8位單片機的,很多用人單位確實也在技能要求裏面提到了會用到32。但是,這並不意味着8位單片機就不行了,說個最俗的因素,8位單片機便宜!

騷尼哥在回答這類問題時,說了一段話,我印象很深:會用STM32不代表牛逼,會用8位單片機不代表不牛逼,能把STM32的項目用8位單片機做出來,這纔算牛逼!

是的,32位單片機確實性能強,但如果用不到合適的地方,就是資源的浪費,這不是一個優秀的工程師該做的事。

很多新人做項目,很少考慮需要用到的處理器性能,動不動就是32位單片機。這對一件商品來說,確實是一件好事,因爲被大衆認可了。但是對一個工程師來說,我不這麼認爲。我印象很深的一件事,一個學生想做個平衡小車,但是角度環調不好,問我怎麼回事。我讓他跟我說下他的硬件方案:他說他用的STM32F4系列的某個芯片(型號我記不清了),電機是網上隨便找的。

我當時的心裏是一陣陣的無力感,F4系列都用上了,呵呵,但是電機這個最重要的因素卻沒認真考慮。

 

爲什麼不用arduino?網上的案例也很多,學起來還簡單。

呵呵...

先說arduino的來源吧。他是意大利的一名教師和一名晶體工程師發明的一個靈活性非常高的電子平臺,主要是因爲當時的學生跟他抱怨找不到便宜好用的微控制器。

Arduino有多好用?

由於我的工作的原因,我和北京一些中小學有接觸。我能感覺到的是,北京這邊,基於arduino的單片機課程,或者機器人課程是非常多的,面向的都是中小學生。所以,中小學生都能學會的編程,有多難?

所以說,它的火爆程度還是很高的。那,能不能用它來做產品?

這就是個很嚴肅的問題了。做產品的話,首先要考慮的是什麼(拋去成本)?

穩定性,穩定性,穩定性!!!

如果穩定性不行,入門再簡單,功能再強大,都是扯淡!明白?

那麼,它的穩定性到底行不行?這其實是一個備受爭議的問題。因爲最初它是由於教學的目的被設計出來的,當前國內用的最多的也只是DIY愛好者和一些中小學的興趣課裏。

羅列一下它在國內的主要用途:DIY工具,中小學生興趣課,還有一些玩具。這樣的背景,導致國內幾乎很少有團隊敢在設計產品的時候拍着胸脯說用它沒問題。

那麼,它真的不行?

注意我的措辭,我剛纔在羅列用途的時候,修飾詞是“國內”。在國外,其實是有很多公司用arduino來設計產品的,當然也有一些成功的商業產品。

爲什麼國內沒有?或者很少?

沒人願意讓自己去試錯。在國內沒有出現大量的成功案例之前,這個現象估計很難改變。舉個例子,我之前曾經在一家汽車電子公司裏工作過。汽車是一個電磁環境非常複雜的東西,選用芯片的時候,公司老闆問的最多的一句話就是:同行有沒有用過這個芯片?

有的話,纔敢放心用。否則,既說服不了自己,也說服不了客戶。因爲一旦出現問題,要麼切換供應商,要麼就召回.....

用汽車電子的例子,可能有些極端,但我想表達的意思是:在沒有足夠案例證明的情況下,它很難被接受。

關於arduino的問題,大家可以看一篇文章:關於使用Arduino做開發的二三理解

百度吧。這篇文章算是說的比較中肯的。簡單來說,在未來,它可能在國內的公司裏推廣開來,目前的話,快速開發一些小批量功能不太複雜的產品可以考慮,否則的話,輕易還是不敢用。

這裏再說個事,之前曾經有個大學生跟我聊天,說他們實驗室的人基本都是用arduino,51,32都不怎麼學。

我當時心裏咯噔一下,第一反應就是:這羣學生被耽誤了....

然後他說,他覺得arduino和傳統單片機差別很大,還是要學一下其它的,否則不好找工作。後面這句話讓我還算欣慰。

然後說說蛋黃!這裏說的不是雞蛋黃,而是某位牛逼的人物自己做的一個超迷你平衡小車,名字叫蛋黃。製作過程非常暴力,以arduino爲控制核心,用到了銀行卡,502膠水,洞洞板,熱熔膠,從別處拆來的電機、舊手機的電池,樂高積木,各種電子模塊。總之,動手能力強的一批。時間跨度好幾年,他做了三個版本,第一個長這樣:

         靈感來自於機器人瓦力。功能上和大部分平衡車一樣,兩輪直立,藍牙遙控等。

         第二階段,據說因爲他們學校有了3D打印機,所以想換個外殼,於是折騰了一下。第二個長這樣。

         相比第一個版本,功能多了很多。例如:蜂鳴器報警、擡頭舵機互動、超聲波測距、攝像頭感應、OLED屏幕顯示。我當時很難想像,他怎麼把這麼多功能都搞進去的。看來真的是老師佈置得作業太少了!!!

         第三階段,把廢舊的安卓手機和平衡車結合起來,做成了這個高端大氣上檔次的機器人管家。因爲是基於安卓平臺,所以他融入了視覺、語音、3D、物聯網等因素。

 

         到了第三階段,我其實已經不太在乎它有什麼功能了。因爲,無論他弄出什麼功能來,貌似都很正常。

 

         那麼,我要做的是個什麼樣的平衡小車呢?

面對這麼優秀的愛好者作出的作品,我想了很長時間,我在想我到底應該做一個什麼樣的。跟他一樣那沒有意義,而且還不見得做得比他好。

我想了想,覺得有幾以下幾點是我應該要做到的,

1、要有學習的意義,就是說這個板子不光能跑平衡小車,還要作爲一個學習的開發板,這是最基本的。

2、選型方面要合理,就像我最開始說的,學會32位的單片機並不見得比學會8位的單片機厲害,能用8位的單片機把32位的單片機的項目做出來,這才叫厲害,所以在做這個東西的過程中,儘量選擇合適的資源。每一個元器件的選型都要有原因,有做產品的意識,同時要實現它的效果。

3、製作過程要儘量低成本。身爲DIY愛好者,很多人會有這樣的感覺,一樣東西做的過程是非常興奮的,演示的時候也非常興奮,但是演示完了三天之後這個東西就開始喫灰了。所以爲了防止這的情況出現,或者即便出現之後這個東西喫灰的情況,但因爲它的價格也不是很高,不會心疼。所以我們儘量使用低成本的東西來實現。

4、組裝過程要儘量簡單。儘量避免太過複雜的組裝過程,例如像蛋黃那樣,很秀,但也會把大部分人難住,這樣的方案需要極高的動手能力,對很多人來說這也是一個非常大的門檻,所以這一點也要儘量避免。

 

從這裏開始,如果是剛入門的單片機愛好者或者想做東西練手的人,注意了。因爲接下來的內容,我會用很長的篇幅講述平衡小車的原理,以及製作過程中遇到的問題。這種剖析式的講解能把製作過程中遇到的80%以上的問題解決掉,剩下20%是基礎。

所以,沒基礎的或者已經做過的就當故事看了。

 

想清楚這幾點之後我就開始動手準備了,首先是單片機,我選用的是stm8s103f3P6,這是一個20管腳的單片機,flash空間只有8k rom,1k的ram。在選之前,其實我自己也不知道這個東西能不能實現我的要求。但隨着設計的過程進慢慢的進行,我發現它遠遠夠超出我的預期,功能是非常強大的。

記得之前我在貼吧看到一篇帖子,就是在描述這個單片機,當時他把stm8s和傳統的51做了一個對比,把它稱爲8位單片機的性價比之王,這個說法雖然有些誇張,但是在一定程度上也體現了這個單片機的功能強大。

我爲什麼會想到選這個芯片,其實是因爲之前在淘寶上閒逛的時候,看一些最小系統板。當時看到他的照片的時候有一絲驚訝的感覺,因爲它的體積非常之小,注意是最小系統板,它和一個一元的硬幣放在一起也依然顯得非常小巧,所以當時忍不住就買了幾個回來做測試,結果發現非常好,然後價格也不貴,當時的價格我記得是3塊錢左右。放個圖:

         我當年買的時候是三塊多,現在漲了點。

 

角度傳感器這個就不用說了,MP6050因爲用的比較多,網上資料也比較多,價格也合適,所以就選它。

然後是電機驅動的部分,這裏有兩個選擇,一個是L9110s,另外一個是tb6612,另外一個還有傳統的l298n,但是那個東西體積非常太大,太醜了,我不喜歡,所以把它拋棄掉了。

那L9110S和TB6612怎麼選?

這兩個模塊其實我都有買回來測試。先說L9110S,當時的價格比TB6612低一點,測試過程中發現有兩個問題:一個是發熱比較嚴重(據說後來新的芯片解決了發熱的問題),當時我甚至加了散熱片,只跑了幾分鐘就熱的不行;另一個是能量轉換效率貌似不高,打個比方,同樣用50%的佔空比驅動電機,只用肉眼觀察,TB6612比L9110S明顯要快一點。

注:我說的這些數據都是2016年~2017年做測試得出的結果,現在可能有了變化,所以僅供參考。

還有一件事比較詭異,2019年下半年,TB6612在淘寶上幾乎斷貨。部分有貨的,價格從四五塊錢直接張到了20左右。咋回事?

 

然後是電池,電池最開始選的時候我也沒有什麼經驗,所以就各種電池都買了一些,4.2伏的,8.4伏的都有。

然後是電機,電機的話,我主要看中了一款n20的電機,據說性能比較好。所以我在淘寶買了一些。看了一下各方面參數都還可以,但是帶碼盤和不帶碼盤的電機價格差別有點大,但是前期研發先不管,買回來再說。

最後是輪胎,剛好和n20電機配套的,有一款D字型的橡膠輪胎,外形也是非常的可愛,然後就買了一些回來。

然後就開始搞事情了。

首先是搭建這個小車的結構,我一開始並沒有直接使用PCB來做車身,也沒有用亞克力板子來做車身,我使用的是洞洞板,按照一定的尺寸評估整個車身的大小,然後用剪刀裁定的尺寸,然後使用銅柱進行多層的結構組裝。

組裝的過程也是非常的暴力,剪子鉗子,熱熔膠,螺絲刀,各種工具都要上,還有杜邦線,電烙鐵等等。

組裝的過程很慘烈,出來的外形自然也就沒那麼好看了,這裏應該還有當年組裝的外形,放個圖給大家看一下,這就是當時最早的一個版本。比較髒也比較難看,現在已經放在一邊喫灰了。

 

可以看到左邊是MPU6050,右邊是STM8S的最小系統板。上下兩層洞洞板,採用銅柱做固定。

怎麼確定這個新組裝出來的結構可以用,這是一個最基本的問題。但是好在我有之前買的那個平衡車,於是我把它的控制板拆下來,然後使用我新買的電機、輪胎、電池、角度傳感器、電機驅動模塊組成的車身,這樣組裝在一起做了一個測試。

這個時候第1個問題出現了,就是使用32的平臺來控制這個結構時。如果使用的是DMP方式讀取MPU6050的角度,控制小車,是可以站立的;但如果使用原始數據轉化爲角度再去控制的話,幾乎是站不住的。

發現這個問題是非常嚇人的,因爲如果必須使用DMP方式的話,那就跟我的初衷相違背了。所以這個問題必須要想辦法解決。

於是我又開始了長時間的上網查資料,這次查資料的時候,主要的重點放在小車的結構上面。

什麼樣的結構小車最容易平衡站立,而且站立的最穩,是不是要重心低一點?還是要質量分佈均勻一點?還是結構要大一點?

 

甚至我回想起了小時候玩的一個遊戲,就是用一根手指,把一根木棍立在一根手指上,看如何能保持這根棍子的直立。到底是質量大的棍子容易直率還是質量小棍子容易直率。

隨着結構和程序的不斷優化,我慢慢發現了這個問題的核心點,根據我的回憶,當時最核心的地方在於,由於我是用的是原始數據計算角度的方式,這種方式和DMP方式計算出的角度有一定的偏差。而這個偏差會導致當小車發生偏移的時候,我的電機沒有辦法快速的給出響應,也就是說反應速度不夠。

有些人看到這個問題,第一反應就是8位的處理器速度不夠,但其實你忘了我在上面貼出的第1個例子,他使用的單片機就是8M的時鐘,而這裏我使用的stm8s,我已經把它的時鐘設置爲16M,所以這個時鐘的因素是可以忽略的。

然後引起我注意的是一條不太起眼的消息,就是網上有人在討論小車結構的時候會說到車身越大、平衡越好掌握;越小、越不容易掌握。因爲大的車身它發生偏移的時候,需要的時間長一些,而小的車身發生傾斜的時候,時間貌似更短,所以這就需要更快的反應速度。

這個時候就需要一個控制算法的出現了,前面也提到過,就是PID。因爲當前市面上大部分平衡小車的套件,他們使用的電機性能比較強,同時車身也比較大,所以電機的響應能力和速度是完全可以應付車身的,處理小車傾斜時面對的狀況。

但是我現在選了一個車身比較小的結構,同時電機扭距不是特別強的電機。那麼這個電機的性能就需要一些特殊方式來提高,而提高響應速度最直接的方式就是使用PID這個算法裏面的參數I,也就是積分。積分的特性就是它會累積誤差,時間越久累積的誤差越大,它糾正的力度也就越大,當然這個時間久並不是咱們人體感應的時間,而是單片機的時間。對他來說幾個循環過去,如果發現誤差還在繼續增加,那麼它會產生非常強大的修正的力,這個力會作用在電機上,最終使小車的車身恢復平衡。

終於把這個因素考慮進來之後,小車顫顫巍巍的站了起來,第1個問題順利解決。

 

發現他搖搖晃晃的站了起來,這個時候我可以確定這個結構是可行的。

這個時候工作要分兩個方向同時進行,一個是電路板的繪製。當時第1批板子,我使用的是autumn designer這個繪圖工具。當時我印象裏應該是畫了兩三個版本,然後發給嘉立創去打樣。現在還能找到當時的板子,隨手放一個圖。

         可以看到,那個黑色的是散熱片,下面緊挨着L9110S模塊。中間的兩個排母用來接STM8S的最小系統板,MPU6050挨着L9110S在另一個角落。

另外就是程序的編寫,stm8s的單片機從我買那個最小系統板回來之後還是第1次用,但是編程方式和其他單片機都是大同小異的。只要注意一下細節,網上搜幾個例程,搜幾個參考的工程,基本上都是可以玩上手的。況且,賣家當時還提供了很多基礎的資料,上手完全沒有問題。

而且當時我心裏想的是32我都玩了,8我還玩不了呢,這是一個很簡單的邏輯問題。

 

準備程序的移植和編寫,當時在32這個平臺上,我已經可以正常使用了,但是移植到stm8這個平臺上,還需要一些工作。基礎框架是沒有問題的,使用普通IO模擬IIC總線讀取MPU6050的數據,但是因爲stm8s103f3P6這個芯片的flash非常小,所以沒有辦法使用DMP的方式讀取比較高精度的數據。因此,所以這裏使用的是讀取原始數據,然後解析的方式。

也就是直接讀取加速度和角速度,然後使用重力垂直向量的方式進行解析,這樣來獲取角度。這個思路也很簡單,如下:

初始狀態是,加速度計讀數是A_X =0; A_Y=0; A_Z=1g;如下圖:

 

然後旋轉一定角度後是這樣:

 

旋轉後仍要保證豎直方向是1g的加速度,所以有將X軸和Z軸的加速度值矢量疊加後爲1g即可用反正切求出P的大小來了

如圖:

 

即可得

Angle = atan2(Acc_x,Acc_z);(注意:這裏得出來的角度是弧度)

(上面內容轉自CSDN博客:基於MPU6050的加速度求角度

        

當時出現的第2個問題是,小車雖然站了起來,但是抖動和晃動是比較明顯的,不是一個非常平穩的過程。怎麼辦?

剛好那段時間認識了做四軸的小馬哥,他對MPU6050瞭解應該比我強,所以當時在網上簡單諮詢了一下。但因爲小馬哥看不到實物,不好分析。

這個時候我從兩個方向去考慮問題,首先是結構上,有一部分原因我會懷疑這個小車的車身重量太輕,導致電機在對小車進行糾正的時候力度過猛,使小車產生震盪。

針對這個考慮,我在小車底部用膠粘了很多銅柱,增加車身重量,發現沒有效果,然後又把這些銅柱放在車身頂部,然後又把它們擺成了各種形狀,要麼是長的要麼是直立的,總之增加小車的質質量,進而增大它的慣性,但是這種方式依然沒有效果。

 

第2個方向是對程序進行優化。例如調節PID參數、調整程序循環週期、在PID算法的基礎上做微調等等,效果都不明顯。

這裏說一下,當時使用的濾波算法是卡爾曼濾波,是從那個不靠譜的STM32小車賣家那裏移植過來的。

後面我在想,是不是算法移植有問題。查了一下資料,果然!已經有網友寫成了可直接使用的庫文件,同時,在使用卡爾曼濾波的時候,需要對相關參數做調整,最主要的應該是週期!

調整完成之後,小車從哆哆嗦嗦的狀態,一下子變成了平穩的滑翔者!當時夜裏11點多,我媳婦睡的呼呼的,我激動的把她叫醒,演示了一下我的樣品。然後她給了六個字的評價:

別煩我,睡覺呢!

嗯,謝謝鼓勵!

到這一步,角度環已經沒有問題了。當時我還在QQ空間發了個視頻,顯擺了一下。當時很多人都希望我趕緊弄完,然後發教程。但誰知,一等就是兩年~~~

原因很簡單,第一年我卡在了路程環上,第二年我去忙別的事情了~

直接說路程環吧!

平衡小車的站立,至少需要兩個環!一個是角度環,維持小車平衡。但是維持平衡還不夠,你會看到它平衡的到處亂跑,不服從指揮。

所以需要第二個環:路程環(也有人叫速度環)。它能讓小車原地不動,或者按照我們的要求移動。原理也很簡單,它會監測小車輪胎的轉速和轉向,從而對小車的移動進行糾正。

爲什麼說至少需要兩個環?

有的人還會做轉向環,假設,如果有外力導致小車旋轉了90°,那麼也要把這個旋轉糾正過來。

爲什麼說我在這裏卡了一年?網上不是有很多方案嗎?你手裏不是也有樣品嗎?

確實,如果要做一個跟我手裏一樣的,一點都不難。但我不想做那樣的,我用的是N20的電機,這種電機帶碼盤的很少,而且價格高的不正常!

有多高?

電機不加編碼器,價格十多塊。加了編碼器之後,價格變成了37塊錢!

自己定做一批高精度碼盤?

一個是成本會有較大的提升,另外就是違背了我的初衷。我的其中一個初衷就是:儘量使用低成本、市面上現成的元件來製作這個小車。

一個電機十多塊錢,但如果加上碼盤,要賣到37!兩個就70多!兩個一元硬幣大小的電機,賣70多,很難接受!

這個問題從2017年初就開始困擾我,怎麼搞?再這麼拖下去,外甥都要上大學了!!!

同期,卡着我的還有另一個問題,路程環的問題。假設,我真的沒得選,用了37塊錢一個的電機,能不能實現路程環?

這個我試了一下,雖然有些坎坷,但還是能用的。難道真的要用這個?

先給外甥做一個玩具出來吧,一方面做驗證,另一方面,再拖下去,我這個舅舅的尊嚴就徹底沒了。

做的過程很順利,採用了8.4V的鋰電池,轉速一分鐘300轉的電機,外接了一個藍牙串口模塊,可以接手機,通過藍牙串口助手發送指令,實現手機遙控的效果。在家附近找了個公園,測了一下無線傳輸的距離,撐死二三十米。但是忽悠小朋友足夠了!

 

同時,繼續查資料!

所以,這一階段的主要問題是:如何在不使用測速碼盤的情況下,或者是一些別的方式,實現小車原地站立。

查了很久,還真查到一個思路,還是最開始那個帖子。

那位前輩,也考慮了跟我一樣的問題:不使用速度環,能否實現位置的維持!

他在處理這個問題的時候,思維上升到了能量的層面。小車在向前移動或者向後移動的時候,肯定會消耗能量。如果把前後消耗的能量抵消,那麼小車就能原地不動了。

怎麼計算這個能量?

說來也簡單!把小車每個週期下,驅動電機的PWM的佔空比,以及電機旋轉方向記錄下來,做累加。向前爲正,向後爲負,儘量保持累加和爲零。進而實現小車的位置原地不動。

有沒有效果?

據這位前輩說,有一定的效果,但是會隨着時間不斷偏移,偏移比較明顯。

呵呵,這位前輩很調皮啊!這麼搞,自己玩玩可以,不能做爲作品對外分享啊。

怎麼辦?

那段時間差不多每天都在想這個問題,有時候睡覺也會想~

頭疼了很長一段時間,終於出現了轉機。

 

第一個問題的轉機,我印象裏出現在2017年下半年。

這裏不得不提到一個人:孟瑞生,他曾經在電子發燒友論壇衆籌STM32的開發板。我之所以注意到他,是因爲他畢業於中北大學。

是的,跟我一個學校,也就是我師兄。

後來他去了嘉立創,創建了技新網。技新網主要做各種模塊,方便工程師做驗證。他們曾經推出過一款產品(非平衡車),上面同樣使用了N20電機,同樣對該電機進行了測速,但測速方式卻和傳統的平衡小車完全不一樣。

傳統的電機在測速的時候,他們是在電機的旋轉軸上加了一個碼盤,這樣電機在旋轉的時候可以測出它的轉速,還有旋轉方向,這個碼盤可以是光柵碼盤也可以是霍爾碼盤。

放個圖:

 

         這裏借用平衡小車之家的圖給大家說下。

         左邊的電機在電機旋轉軸上增加了一個霍爾碼盤,電機轉一圈,碼盤輸出13個信號(數量多少根據碼盤結構)。而右邊的電機,在旋轉軸上增加了一個光電碼盤,碼盤旋轉一圈可以輸出500個脈衝。

         無論是13還是500,都是減速前的脈衝個數,如果電機減速比是30的話,前面的數字還要乘以30.13X30或者500X30,就是小車輪胎旋轉一圈輸出的脈衝個數。

 

技新網是怎麼做的?

他們使用了一個紅外反射式傳感器,做了個模塊,利用輪胎自身的結構,組成了一個另類的測速裝置,如圖:

 

         核心是裏面用到的芯片:ITR8307這是一個紅外反射式傳感器,芯片表面由兩部分區域組成。一部分用來發射紅外光,另一部分用來接收紅外光。如果能接收到,說明芯片表面有類似鏡面的物體存在,那麼,這有什麼用?

         看輪胎!

         早期的賣家在寶貝詳情裏會說一句話:輪胎自帶編碼器(現在好像看不到了)。

         原諒我才疏學淺,孤陋寡聞!很長時間,一直沒明白自帶的編碼器在哪,怎麼用!直到技新網做了上面那個模塊,我才明白過來。

輪胎內部自帶白色牙齒(原諒我用“牙齒”這個詞),共有12個。他們把紅外反射模塊固定在牙齒下面,當輪胎旋轉時,牙齒會依次、間斷的從傳感器上面經過,出現的效果就是高、低、高、低電平的不斷輸出。單位時間內計算脈衝信號個數,速度有了~~~

注意這裏的脈衝個數,上升沿12個、下降沿12個!輪胎轉一圈只有24個!

 

然後是方向。很遺憾,這種編碼器沒法計算方向。但是無所謂,我只需要在檢測到高低電平的時候判斷一下電機的驅動方向就行了,畢竟當前脈衝個數不多,精度一般。

而這種解決方案的成本,相比37塊錢一個電機的價格,簡直便宜的不像話。

電機測速問題解決了,但是路程環怎麼搞?

前面說了,常用的測速碼盤,旋轉一圈,輸出的脈衝個數,要麼300+,要麼上千。而這裏的碼盤,旋轉一圈,輸出24個脈衝!!!

這個數量級的差別,導致我在調試路程環的時候幾乎無從下手!現有的程序移植過去,上電,幾乎看不到路程環起作用。如果把路程環裏的PID參數調大,最直觀的現象就是小車變得劇烈的抖動,然後倒下。

怎麼辦?

那段時間差不多每天都在想這個問題,有時候睡覺也會想~

頭疼了很長一段時間,第二個問題終於出現了轉機,結果就是算法方面要換一種思路。前面說了,角度環已經沒有問題,有問題的是當前狀態下的路程環。解決這個問題只有兩個方向:1、優化;2換思路。

我選擇了第二個,怎麼換的思路?這裏不得不提到我的岳父大人,他除了是我岳父,還有一個身份,就是一位老中醫,老武術家。有一些人跟他學武術,週末的時候經常聚在一起練習。

我跟着去過幾次,有一段對話讓我印象很深。當時是一個人想他提問,關於搏擊的問題。我岳父具體怎麼回答的我已經記不清了,大致意思就是:

“兩個人搏擊,目的就是把對方放到。而放倒對方最核心的方式,就是破壞對方的重心!”

是的,破壞對方的重心。我當時對這段話印象深,是因爲我岳父的學歷,說實話不是很高(這裏沒有任何意思,只是陳述一個事實),但是卻能用一種很科學的方式來描述這個問題。讓我很是驚訝!

而後期我頭疼的那段時間,這句話時不時出現在我腦子裏。所以我在想,會不會有什麼啓發的作用?注意,下面是我的思考過程(你們也可以自己先想一下):

 

小車的站立也要保持重心平衡,如果不平衡,那麼就會往一個方向偏。在這個過程中,我要阻止外力對小車重心的破壞。

小車的平衡靠角度環可以實現,但是會偏。怎麼不讓它偏?

由於小車的車身質量分佈並不均勻,導致小車水平的時候可能並不是它的平衡角,那就需要找到這個平衡角。小車維持平衡的角度,剛好是小車重心垂直過電機軸的角度。所以小車初始調試的時候,需要先找平衡角。

假設已經找到了平衡角,在平衡角狀態下,外力導致小車向前走了7步,我可以通過碼盤測速測出來。那麼,怎麼糾正?

重心!

是的,我可以讓小車的重心平衡角向反方向增加0.7°。這樣角度環爲了維持平衡,會自動往反方向糾正。往回走一步,重心平衡角上面添加的誤差少一點,回到原地,角誤差清零。

 

當我想出這個方法的時候,腦子是極度興奮的!因爲我相當於拋棄了傳統的路程環,重新設計了一種控制思路。同樣是夜裏十一點多,我把這種思路轉化爲代碼,編譯、燒錄、上電。

現象跟我想的一樣,小車以一個位置爲原點,做往復運動!

在這種情況下,只需要把偏差和重心結合起來,使用PID的方式計算出一個糾正用的誤差角,疊加到小車的平衡角上就行了。而傳統的路程環就徹底被我拋棄了,這種新的PID環,如果之前沒有人用過的話,我想把它叫做重心環。

 

問題解決了,那幾天腦子異常興奮,開始準備後續的事情了。

 

我準備做一批,既可以做玩具,又可以當做最小系統板,還能以項目的形式學到東西。

接下來依然是三步走:

1、確定方案,畫原理圖、PCB,找工廠安排制板、焊接、組裝;

2、編寫教程;

3、給小車起個名字。

先說起名字的事,叫什麼?

我和我媳婦想了好幾天:

煎餅一號?蹭煎餅俠熱度~~~

青蛙一號?板子綠的的就叫青蛙?下次制板變成紅的,是不是還要叫蜻蜓?

舅舅一號?給外甥做的就叫舅舅一號?萬一升級到舅舅二號,別人會以爲他有兩個舅舅。

後來想了想,解決小車技術的一個關鍵點是重心環的出現,所以我覺得應該和重心相關比較好,想起了之前的一部電影《地心引力》,就叫:地心一號吧!

 

硬件方案方面:

STM8S103F3P6+MPU6050+TB6612+藍牙串口模塊+紅外遙控

藍牙串口模塊在這裏有兩個功能:一個是調整PID參數的時候,可以終端界面無線測試;另一個就是在鍵盤界面控制小車的行駛方向。

電池最開始我選的8.4V,也就是兩片4.2V的串聯。但是後面發現有4V左右1分鐘300多轉的電機,那自然就換回了4.2V的電池。目的很明確,節約成本。但同時引發兩個問題:

1、STM8S工作電壓3.3V,電源芯片怎麼選?1117-3.3? 那是肯定不行的,這個問題我不直接給出答案,想知道的,搜一下“LDO”的意思,再看看1117-3.3的數據手冊就行了

2、電池電壓降低,小車的馬力自然也降下來了,最直觀的表現就是:它只能在室內光滑的瓷磚上走,路面坎坷的情況下,是走不了的。所以,如果有朋友想要大馬力的,需要更換電池和電機。

 

但是不管怎麼說,老夫很欣慰!

這個時候又出了一件事,絆了我一下~~~小車真的是命途多舛啊~~~~

什麼事?

STM8S103F3P6漲價了!之前一片2元左右,你知道2018年漲到了多少嗎?

當時嘉立創的價格從二點多一路漲到了15元!!!這個破玩意賣15!!!

可惜當時我沒有截圖,當時嘉立創寶貝詳情頁面上還標了是廠家管控的原因。當時有個說法,說是因爲2018年意法半導體在推STM8S001,一個SO-8封裝的8腳單片機,爲了給它讓路,所以搞了這麼一堆破事。

2019年,總算價格下來了。陸陸續續,事情開始進行。生產方面,事情安排下去就行了,比較省心。

最後是教程,看過我51教程的人都知道,我做教程,喜歡把複雜問題簡單化。每一節,儘量控制時間不超過20分鐘,儘量講幾個知識點。有用、不多,但是很關鍵!學到知識的同時,更能學到方法!

所以又花了一段時間優化教程。關於STM32,很多人都是用庫函數開發的。那麼STM8,教程裏用庫還是寄存器?我當時想了一段時間!因爲庫已經是一種趨勢了,我有預感,庫普及的範圍會越來越廣!所以決定,STM8S的教程用庫函數來開發。當然,如果大家感興趣,後面我會再補一套寄存器的例程。

因爲網上有人分享了一個自動生成STM8S庫函數代碼的工具,所以例程的編寫一直進行的都比較順利。直到2019年8月份左右,出了一個問題!一個很有意思的問題!這個問題我現在已經找到原因,並解決了!

先說下我的開發環境,我使用的是IAR工具,然後從ST官網下載了STM8S系列的外設庫。原理圖在設計的時候,爲了儘量多的給大家增加一些可以學習的東西,同時又因爲STM8S103F3P6管腳比較少。我把一體式紅外接收器的管腳放在了STM8S103F3P6的PD1上,用過這個系列的朋友會知道:PD1不只是一個普通的IO,它還是STM8S的SWIM管腳,也就是下載管腳。

         問題是什麼?

         問題就是,當我使用庫函數的方式,用PD1管腳做紅外遙控器的解碼的時候,PD1無法正常工作。解碼方式就是51裏常用的定時器+下降沿中斷的方式。

         有人肯定會說,數據手冊裏有說明:PD1要當普通管腳用的話,需要禁用SWIM功能。

         呵呵,你覺得我沒看嘛?

         我可以負責任的告訴你,不管你有沒有禁用SWIM功能,PD1都能當做普通IO使用?

         爲什麼?

         因爲我最初調試小車時,就是使用寄存器的方式寫的,這些功能全都驗證了一遍!!!現在這些代碼還在我電腦裏放着。

         所以,這就很有意思了,這是怎麼回事?

         可以給你們一些思考時間,再往下看。

         我當時找了一個STM8用的比較好的朋友,請他幫我寫了一個測試程序,使用PD1管腳,庫函數方式。很快,他寫完發給我了。

         結果我打開一看,傻眼了,他用的是另一個開發工具:STVD。

         是的,開發STM8S,有幾種不同的工具,IAR、STVD都可以,都支持官方的庫函數。

         他發來的程序能不能用?     肯定是能用的,因爲我這個朋友寫代碼比較嚴謹,要麼仿真驗證、要麼實物驗證,而且風格一向很好。

         怎麼辦?當然是讓他重寫,用IAR。

         果然,他也遇到問題了。PD1一旦遇到下降沿中斷,定時器的時間就跑的亂七八糟,狀態很不穩。他跟我說了一下,我基本已經斷定問題在哪了。

         福爾摩斯說過一句話:排除掉所有的不可能,剩下的,無論多麼不可思議,它就是真相!

         現在已經驗證過的是:IAR+寄存器編程、STVP+庫函數編程都沒有問題,芯片、下載器、電路更沒有問題。剩下的,就是IAR出了問題!是的,它對庫函數的支持有問題!

         而且這個結論出來以後,我瞬間想起了以前用庫函數的時候,出現的一些奇怪的問題,都能解釋清了。

         現在的問題是,怎麼辦?教程已經錄到結尾了,總不能又重新錄吧。

         想了想,也有辦法!

         混編!

         是的,同時使用庫函數和寄存器的方式進行編程。這種方式對新手來說可能有些奇葩,但其實早就存在了。更早的瞭解到這種方式,對新人來說,可能是一件好事。STM32裏混編可能用的相對多一些,但這不影響。問題已經確定了,把和問題相關的部分代碼都換成寄存器方式編寫的,調一調~~~OK

         所以,到最後,我拿出來的是這樣的一個作品:

         它精緻、迷你、強大!

它不完美,甚至有缺陷!但是,它的出現讓人期待,讓人相信美好的事情總是會發生的。它的功能,我可能會持續優化下去,如果有感興趣的朋友,也可以一起優化。資料稍後我會放到網盤,也可能會放到github上。

         希望你們喜歡——地心一號!

地心一號

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章