BBB 的板上有五個 LED 燈,一個電源,四個其他指示燈,usr0 至 usr3 。這次學習是控制 usr0 至 3 讓它們亮著,熄滅,閃。算是個 Hello World 實驗。非常簡單。 需要的材料: BBB 一臺 購買BBB 自帶的數據線一條 手提電腦或台式電腦,有 USB 插頭的 首先用數據...
BBB 的板上有五個 LED 燈,一個電源,四個其他指示燈,usr0 至 usr3 。這次學習是控制 usr0 至 3 讓它們亮著,熄滅,閃。算是個 Hello World 實驗。非常簡單。
需要的材料:
- BBB 一臺
- 購買BBB 自帶的數據線一條
- 手提電腦或台式電腦,有 USB 插頭的
首先用數據線把 BBB 和電腦連接,自動開機了之後,可以開始了。
這次三個做法都試試:
- Bonescript
- Python
- C++
Bonescript
操作 Bonescript 做法是用 Cloud9,假設你沒改過 BBB 的 usb0 網卡地址的話,從電腦瀏覽器打開 http://192.168.7.2:3000/ 即可。
右擊文件夾目錄添加個文件夾吧,然後右擊添加文件(New File),命名註意擴展名,bonescript 是 JS,擴展名是 .js。
var b = require('bonescript');
var leds = ["USR0", "USR1", "USR2", "USR3"];
for(var i in leds) {
b.pinMode(leds[i], b.OUTPUT);
}
var state = b.HIGH;
for(var i in leds) {
b.digitalWrite(leds[i], state);
}
(話說安裝了新的 OpenWriter 沒有 code snippet 插件…)
首先 pinMode 設 output,LED給它 HIGH 用 digitalWrite 寫進去即可。迴圈四個燈讓它們全部點亮。給它 LOW,LED 就熄滅。試試。代碼寫好直接按上面的 Run 按鈕運行。
然後是閃動,JS 就是個 setInterval 而已:
var b = require('bonescript');
var leds = ["USR0", "USR1", "USR2", "USR3"];
for(var i in leds) {
b.pinMode(leds[i], b.OUTPUT);
}
var state = b.HIGH;
function toggle(){
if(state===b.LOW){
state = b.HIGH;
} else {
state = b.LOW;
}
for(var j in leds){
b.digitalWrite(leds[j],state);
}
}
setInterval(toggle,1000);
再可以加點代碼讓四個燈迴圈點亮熄滅,自己試試把。Bonescript 的 API 請查看這裡。
Python
到了 Python 有點糾結,因為 Adafruit_BBIO 這個 module 有點問題,本來想直接用,但 usr0 沒反應,實測過確實不行。詳細我不研究了,遇上這些事比較惱火不看它了。
直接看看這些東西的工作原理,直接寫吧。為求快捷,先看看 Stackoverflow 別人貼的一段代碼,python3 的,請無視,只看代碼:
import os
class SimpleGPIO:
def __init__(self,gpio_pin):
self.gpio_pin = gpio_pin
os.system("echo %d > /sys/class/gpio/export" % self.gpio_pin)
self.gpio_path = "/sys/class/gpio/gpio%d/"%gpio_pin
with open(self.gpio_path+"direction") as f:
self.direction = f.read()
def write(self,value):
if self.direction != "out":
os.system("echo out > %sdirection"%self.gpio_path)
self.direction = "out"
os.system("echo %s > %svalue"%(value,self.gpio_path))
def read(self):
if self.direction != "in":
os.system("echo in > %sdirection"%self.gpio_path)
self.direction = "in"
with open(self.gpio_path+value) as f:
return f.read()
在 linux 操作硬體,用的是 sysfs ,以上代碼是 GPIO 通用的 class,給 pin 號碼創建即可,然後就可以調用 write 和 read,比較簡單。如果是 python 控請自行按需改良以上,留著日後用。
然後看看 usr0 至 usr3 的燈在哪裡,還有它們可以怎麼玩:
在 /sys/class/leds 內,你會看到四個, beaglebone:green:usr0 至 3,再進去其中一個看看
簡單英文能看懂的話,裡面東西都寫的很明白,咱們要它亮,和滅而已,只需要動 trigger,和 brightness,腳本試試效果唄,拿 usr0 開刀,下圖顯示了原來的值,和我寫入了什麼進去:
echo none > trigger
echo 1 > brightness
這時候,usr0 燈就是常亮的了,因為 trigger 設成 none,亮度為 1。那滅了它呢,就這樣:
echo 0 > brightness
就是說,要它閃的話,首先清掉 trigger(改為值 none),然後把 brightness 迴圈寫入 0 和 1 即可。python 寫也只不過是這樣而已:
import os
import time
class SimpleLED:
def __init__(self,led_no):
self.led_no = led_no
self.led_path = "/sys/class/leds/beaglebone:green:usr%d/" % self.led_no
os.system("echo none > %strigger" % self.led_path)
self.state = "off"
def On(self):
if self.state != "on":
os.system("echo 1 > %sbrightness" % self.led_path)
self.state = "on"
def Off(self):
if self.state != "off":
os.system("echo 0 > %sbrightness" % self.led_path)
self.state = "off"
LEDs = [SimpleLED(i) for i in range(4)]
while True:
for j in range(4):
LEDs[j].On()
time.sleep(1)
for j in range(4):
LEDs[j].Off()
time.sleep(1)
你喜歡用 Cloud9 就開個檔案貼以上代碼上去,然後 run 即可,或者命令行執行,效果一樣。閃呀閃…
Adafruit 那個到底有什麼問題我不研究了。自己動手,豐衣足食。很簡單的。代碼就是創建 SimpleLED 時把 trigger 寫入 none,要開燈 On() 時候對 brightness 寫入 1,關燈 Off() 寫入 0。
把原來的值寫回去 trigger 和 brightness,即可還原,或者傻一點,重啟亦可。
C++
sysfs 說明見 python 部分,C++ 直接上代碼:
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
using namespace std;
#define LED_PATH "/sys/class/leds/beaglebone:green:usr"
class LED{
private:
string path;
int number;
virtual void writeLED(string filename, string value);
virtual void removeTrigger();
public:
LED(int number);
virtual void turnOn();
virtual void turnOff();
virtual void flash(string delayms);
virtual void outputState();
virtual ~LED();
};
LED::LED(int number){
this->number = number;
ostringstream s;
s << LED_PATH << number;
path = string(s.str());
}
void LED::writeLED(string filename, string value){
ofstream fs;
fs.open((path+filename).c_str());
fs << value;
fs.close();
}
void LED::removeTrigger(){
writeLED("/trigger", "none");
}
void LED::turnOn(){
cout << "Turning LED" << number << " on." << endl;
removeTrigger();
writeLED("/brightness", "1");
}
void LED::turnOff(){
cout << "Turning LED" << number << " off." << endl;
writeLED("/brightness", "0");
}
void LED::flash(string delayms = "50"){
cout << "Making LED" << number << " flash." << endl;
writeLED("/trigger", "timer");
writeLED("/delay_on", delayms);
writeLED("/delay_off", delayms);
}
void LED::outputState(){
ifstream fs;
fs.open((path + "/trigger").c_str());
string line;
while(getline(fs, line)) cout << line << endl;
fs.close();
}
LED::~LED(){
cout <<"Destroying the LED object with path: " << path << endl;
}
int main(int argc, char* argv[]){
if(argc != 2){
cout << "Args error, on/off/flash/status supported only." << endl;
return 1;
}
string cmd(argv[1]);
LED led = LED(3);
if(cmd=="on") led.turnOn();
else if (cmd=="off") led.turnOff();
else if (cmd=="flash") led.flash("100");
else if (cmd=="status") led.outputState();
else {
cout << "Command invalid" << endl;
return 1;
}
return 0;
}
代碼來自 Exploring Beaglebone 這本書。原理和 python 一模一樣,不解釋了。
感覺以上有點侮辱你智慧的話,下一篇來個麵包板,點亮上面的 LED,就會用到 GPIO 了。