2016年8月16日 星期二

MicroPython 簡介

MicroPython 簡介

不知道是什麼原因MicroPython 這塊開發板在國內似乎不是太有能見度 ,相關網頁也少的可憐。在這整理一些所知道資訊做個簡介。

MicroPython 是由來自英國劍橋的理論物理學家Damien George 博士建立的kickstarter 專案所發展出的MCU控制器。這是官方網頁 


MicroPython 是開源硬體,它依循MIT協議發佈。有別於Arduino 使用的類C/C++語言,MicroPython 使用如其名的Python 語言來做開發。Python 相較 C/C++ 屬於高階語言,語法上相對比C/C++ 友善直觀容易閱讀。另外Python是一種直譯式語言,你可以直接就在命令列上就開始下達程式指令而不用經過編譯的程序。


MicroPython 的運作其實就是在板上的STM32F405RGT6這個MCU晶片上實現了一個精簡化的Python 直譯器,直接運行放置在板上的Python 程式。硬體方面基本上Arduino 有的IO種類大概一樣都不少,不過晶片效能上比Arduino 要高出不少。開發方式也很輕便,只需要一條micro USB連接線接上你的電腦,接上後會有一個USB磁碟空間出現


這就是MicroPython 的開發環境,你只需要使用任何文字編輯器開啟main.py 這個檔案就可以始編寫你的程式。例如最基本的點燈儀式的程式碼如下....
# main.py -- put your code here!
import pyb
pyb.LED(4).on()
將程式寫入main.py 檔案保存後,再按上板上的reset按鍵重新啟動....
就可以看到藍色LED燈亮起。點燈儀式完成 w
相同的動作對比於Arduino 的程式碼....

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);
}
MicroPython的程式碼看起來是不是親切友善多了呢 :D

當然Python 開發者最熟悉的直譯器命令列也會有。在window環境下的使用者在電腦上板子後,裝置管理員應該出現一個未知的裝置。對此未知的裝置做驅動程式的更新。將USB空間裡的pybcdc.inf 置換驅動程式後就會得到一個COM  Port 
 
就這是你的直譯器命令列的通訊管道,使用putty 來開啟它,就可以直接下達程式命令。例如經典的hello world ...
或者把之前寫在main.py 的程式拿來這裡下達...
很好~點燈完成 XD
介紹與簡單的gettin start 到此,接下來會不定期整理官方的教學與範例。
請勿期待XD

2016年8月3日 星期三

BeagleBone Black啟用SPI port

安裝Adafruit BBIO python函式庫的程序


被折磨了好久,整理出來免得忘掉

以下步驟建立在BBB image版本2016-06-19 , Kernel: 4.4.12-ti-r31

刷完2016-06-19  image ,以文字編輯器開啟 /boot/uEnv.txt 檔案, 加入以下描述句
nano /boot/uEnv.txt

cape_disable=bone_capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
cape_enable=bone_capemgr.enable_partno=BB-SPIDEV0,BB-SPIDEV1

加入描述句後儲存檔案並退出, 然後reboot 重啟BBB
重啟完成後檢查SPI port 是否成功啟用,輸入
cat /sys/devices/platform/bone_capemgr/slots
ls -al /dev/spidev*
這兩條命令, 應會看到以下結果代表成功啟用
root@beaglebone:~# cat /sys/devices/platform/bone_capemgr/slots
 0: PF----  -1
 1: PF----  -1
 2: PF----  -1
 3: PF----  -1
 4: P-O-L-   0 Override Board Name,00A0,Override Manuf,BB-SPIDEV0
 5: P-O-L-   1 Override Board Name,00A0,Override Manuf,BB-SPIDEV1
root@beaglebone:~# ls -al /dev/spidev*
crw-rw---- 1 root spi 153, 1 Aug  1 08:43 /dev/spidev1.0
crw-rw---- 1 root spi 153, 0 Aug  1 08:43 /dev/spidev1.1
crw-rw---- 1 root spi 153, 3 Aug  1 08:43 /dev/spidev2.0
crw-rw---- 1 root spi 153, 2 Aug  1 08:43 /dev/spidev2.1
root@beaglebone:~#

接著建立一隻C程式來做測式
nano spi_test.c

code內容如下:
/* 
  * SPI testing utility (using spidev driver) 
  * 
  * Copyright (c) 2007 MontaVista Software, Inc. 
  * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> 
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
  * the Free Software Foundation; either version 2 of the License. 
  * 
  * Cross-compile with cross-gcc -I/path/to/cross-kernel/include 
  */ 
 #include <stdint.h> 
 #include <unistd.h> 
 #include <stdio.h> 
 #include <stdlib.h> 
 #include <getopt.h> 
 #include <fcntl.h> 
 #include <sys/ioctl.h> 
 #include <linux/types.h> 
 #include <linux/spi/spidev.h> 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 
 static void pabort(const char *s) 
 { 
      perror(s); 
      abort(); 
 } 
 static const char *device = "/dev/spidev1.0"; 
 static uint32_t mode; 
 static uint8_t bits = 8; 
 static uint32_t speed = 500000; 
 static uint16_t delay; 
 static void transfer(int fd) 
 { 
      int ret; 
      uint8_t tx[] = { 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
           0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
           0xF0, 0x0D, 
      }; 
      uint8_t rx[ARRAY_SIZE(tx)] = {0, }; 
      struct spi_ioc_transfer tr = { 
           .tx_buf = (unsigned long)tx, 
           .rx_buf = (unsigned long)rx, 
           .len = ARRAY_SIZE(tx), 
           .delay_usecs = delay, 
           .speed_hz = speed, 
           .bits_per_word = bits, 
      }; 
      if (mode & SPI_TX_QUAD) 
           tr.tx_nbits = 4; 
      else if (mode & SPI_TX_DUAL) 
           tr.tx_nbits = 2; 
      if (mode & SPI_RX_QUAD)  
           tr.rx_nbits = 4; 
      else if (mode & SPI_RX_DUAL) 
           tr.rx_nbits = 2; 
      if (!(mode & SPI_LOOP)) { 
           if (mode & (SPI_TX_QUAD | SPI_TX_DUAL)) 
                tr.rx_buf = 0; 
           else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL)) 
                tr.tx_buf = 0; 
      } 
      ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 
      if (ret < 1) 
           pabort("can't send spi message"); 
      for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { 
           if (!(ret % 6)) 
                puts(""); 
           printf("%.2X ", rx[ret]); 
      } 
      puts(""); 
 } 
 static void print_usage(const char *prog) 
 { 
      printf("Usage: %s [-DsbdlHOLC3]\n", prog); 
      puts(" -D --device  device to use (default /dev/spidev1.1)\n" 
         " -s --speed  max speed (Hz)\n" 
         " -d --delay  delay (usec)\n" 
         " -b --bpw   bits per word \n" 
         " -l --loop   loopback\n" 
         " -H --cpha   clock phase\n" 
         " -O --cpol   clock polarity\n" 
         " -L --lsb   least significant bit first\n" 
         " -C --cs-high chip select active high\n" 
         " -3 --3wire  SI/SO signals shared\n" 
         " -N --no-cs  no chip select\n" 
         " -R --ready  slave pulls low to pause\n" 
         " -2 --dual   dual transfer\n" 
         " -4 --quad   quad transfer\n"); 
      exit(1); 
 } 
 static void parse_opts(int argc, char *argv[]) 
 { 
      while (1) { 
           static const struct option lopts[] = { 
                { "device", 1, 0, 'D' }, 
                { "speed",  1, 0, 's' }, 
                { "delay",  1, 0, 'd' }, 
                { "bpw",   1, 0, 'b' }, 
                { "loop",  0, 0, 'l' }, 
                { "cpha",  0, 0, 'H' }, 
                { "cpol",  0, 0, 'O' }, 
                { "lsb",   0, 0, 'L' }, 
                { "cs-high", 0, 0, 'C' }, 
                { "3wire",  0, 0, '3' }, 
                { "no-cs",  0, 0, 'N' }, 
                { "ready",  0, 0, 'R' }, 
                { "dual",  0, 0, '2' }, 
                { "quad",  0, 0, '4' }, 
                { NULL, 0, 0, 0 }, 
           }; 
           int c; 
           c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL); 
           if (c == -1) 
                break; 
           switch (c) { 
           case 'D': 
                device = optarg; 
                break; 
           case 's': 
                speed = atoi(optarg); 
                break; 
           case 'd': 
                delay = atoi(optarg); 
                break; 
           case 'b': 
                bits = atoi(optarg); 
                break; 
           case 'l': 
                mode |= SPI_LOOP; 
                break; 
           case 'H': 
                mode |= SPI_CPHA; 
                break; 
           case 'O': 
                mode |= SPI_CPOL; 
                break; 
           case 'L': 
                mode |= SPI_LSB_FIRST; 
                break; 
           case 'C': 
                mode |= SPI_CS_HIGH; 
                break; 
           case '3': 
                mode |= SPI_3WIRE; 
                break; 
           case 'N': 
                mode |= SPI_NO_CS; 
                break; 
           case 'R': 
                mode |= SPI_READY; 
                break; 
           case '2': 
                mode |= SPI_TX_DUAL; 
                break; 
           case '4': 
                mode |= SPI_TX_QUAD; 
                break; 
           default: 
                print_usage(argv[0]); 
                break; 
           } 
      } 
      if (mode & SPI_LOOP) { 
           if (mode & SPI_TX_DUAL) 
                mode |= SPI_RX_DUAL; 
           if (mode & SPI_TX_QUAD) 
                mode |= SPI_RX_QUAD; 
      } 
 } 
 int main(int argc, char *argv[]) 
 { 
      int ret = 0; 
      int fd; 
      parse_opts(argc, argv); 
      fd = open(device, O_RDWR); 
      if (fd < 0) 
           pabort("can't open device"); 
      /* 
       * spi mode 
       */ 
      ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode); 
      if (ret == -1) 
           pabort("can't set spi mode"); 
      ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode); 
      if (ret == -1) 
           pabort("can't get spi mode"); 
      /* 
       * bits per word 
       */ 
      ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 
      if (ret == -1) 
           pabort("can't set bits per word"); 
      ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); 
      if (ret == -1) 
           pabort("can't get bits per word"); 
      /* 
       * max speed hz 
       */ 
      ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); 
      if (ret == -1) 
           pabort("can't set max speed hz"); 
      ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); 
      if (ret == -1) 
           pabort("can't get max speed hz"); 
      printf("spi mode: 0x%x\n", mode); 
      printf("bits per word: %d\n", bits); 
      printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); 
      transfer(fd); 
      close(fd); 
      return ret; 
 }

然後編譯此程式
gcc -Wall spi_test.c -o spi_test.o

連結BBB P9 插槽上 pin18 pin21, 這是SPI0 DIDO
接著執行剛才編譯好的測試程式做自我收發,應該可以看到如下結果代表SPI0通訊正常可使用
./spi_test.o 
 spi mode: 0x0 
 bits per word: 8 
 max speed: 500000 Hz (500 KHz) 
 FF FF FF FF FF FF  
 40 00 00 00 00 95  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 DE AD BE EF BA AD  
 F0 0D  
如果把pin18 pin21 的接線斷開會看到如下結果
./spi_test.o 
 spi mode: 0x0 
 bits per word: 8 
 max speed: 500000 Hz (500 KHz) 
 FF FF FF FF FF FF  
 FF FF FF FF FF FF 
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF FF FF FF FF  
 FF FF

以上步驟完成, BBB SPI port 就可以使用了, 接著要安裝 AdaFruit BBIO 函式庫
確認有連結網路,首先進行 package update
sudo apt-get update

安裝 ntpdate
sudo apt-get install ntpdate
kkk

安裝完成, 執行ntpdate 同步時間
sudo ntpdate pool.ntp.org
kkk

再次package update, 並安裝python 相關工具
sudo apt-get update
sudo apt-get install build-essential python-dev python-setuptools python-pip python-smbus –y

完成後用PIP安裝 AdaFruit BBIO 函式庫
sudo pip install Adafruit_BBIO

完成後輸入以下命令檢查安裝正確
sudo python -c "import Adafruit_BBIO.GPIO as GPIO; print GPIO"

應會看到如下結果表示成功
#you should see this or similar:
<module 'Adafruit_BBIO.GPIO' from '/usr/local/lib/python2.7/dist-packages/Adafruit_BBIO/GPIO.so'>


以上