目前分類:Python 程式設計 (52)

瀏覽方式: 標題列表 簡短摘要

Python & MicroPython 程式設計目錄列表

 

 

Python ftplib.error_perm: 550 空目錄處理方式

Python Class Learning

一次搞懂Python BoxSizer

了解 super() 和 *args and **kwargs

Django Web 程式設計目錄

 

MicroPython & Client-Server 使用Socket

Python Socket 網路設計概念

Python socket TCP/IP 網路程式 - Server & Client程式

Python Socket 網路設計-簡單echo程式 
 

Python Socket 網路設計-簡單ftp client 程式
 

使用wxPython 模組視窗程式設計-第四篇

 

使用wxPython 模組視窗程式設計-第三篇 (元件)

 

使用wxPython 模組視窗程式設計-第二篇(位置管理)

 

使用wxPython 模組視窗程式設計-第一篇


使用python Win32Com模組與Excels 圖表共舞


Python Win32Com Excels基本操作


Python與Excel連結的openpyxl模組


Python 文件收集


使用Pyodbc 連接資料庫


Python py檔轉成exe檔


如何在Portable Python離線安裝模組


MicroPython 程式集


MicroPython 功能集 

MicroPython 中斷處理


GPIO.BOARD與GPIO.BCM設定有何不同?


第一個python程式

免安裝版的Portable Python 2.7.6.1 下載

參考資料:

http://zetcode.com/wxpython/
https://gist.github.com/mikepsn/27dd0d768ccede849051
http://pythonexcels.com/python-excel-mini-cookbook/
http://docs.wxwidgets.org/trunk/index.html
https://www.tutorialspoint.com/wxpython/index.htm

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

Python 各種官方說明文件

(1)Beautiful Soup 4.4.0 Documentation
(2)Pandas 0.25.1 documentation 
(3) Django Documentation Release 3.1.dev

 

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

 

h5py 常用在大數據的資料儲存,相較於 csv 更快速讀寫,並且更符合Pthon 方式。

“HDF” stands for “Hierarchical Data Format”. Every object in an HDF5 file has a name, and they’re arranged in a POSIX-style hierarchy with /-separators:

最基本的操作,讀,寫,更新

Read HDF5

import h5py
filename = 'file.hdf5'
f = h5py.File(filename, 'r')

# List all groups
print("Keys: %s" % f.keys())
a_group_key = list(f.keys())[0]

# Get the data
data = list(f[a_group_key])

Write HDF5

#!/usr/bin/env python
import h5py

# Create random data
import numpy as np
data_matrix = np.random.uniform(-1, 1, size=(10, 3))

# Write data to HDF5
data_file = h5py.File('file.hdf5', 'w')
data_file.create_dataset('group_name', data=data_matrix)
data_file.close()

 

另一個讀取範例

Reading the file

import h5py

f = h5py.File(file_name, mode)

Studying the structure of the file by printing what HDF5 groups are present

for key in f.keys():
    print(key) #Names of the groups in HDF5 file.

Extracting the data

#Get the HDF5 group
group = f[key]

#Checkout what keys are inside that group.
for key in group.keys():
    print(key)

data = group[some_key_inside_the_group].value
#Do whatever you want with data

#After you are done
f.close()

另一個寫入範例

(1) 準備資料

# setting frame = np.zeros((1, 60, 80))

生成一個 dataset ,並預設此 dataset 可以彈性成長

# initialwith h5py.File("mytestfile.hdf5", "w") as f: dset = f.create_dataset('video', data=frame,maxshape=(None, 60, 80), chunks=True)

讀取這個檔案所有的 dataset,目前只有 u"video"# get key with h5py.File("mytestfile.hdf5", "r") as f: print(f.keys())

先擴增 dataset 的大小後,再塞入新的 frame

# extend datasetwith h5py.File("mytestfile.hdf5", "a") as hf:
    hf['video'].resize((hf['video'].shape[0] + 1), axis=0)
    hf['video'][-1:] = frame

 

官網範例及說明:

>>> import h5py
>>> f = h5py.File('mytestfile.hdf5', 'r')

The File object is your starting point. What is stored in this file? Remember h5py.File acts like a Python dictionary, thus we can check the keys,

>>> list(f.keys())
['mydataset']

Based on our observation, there is one data set, mydataset in the file. Let us examine the data set as a Dataset object

>>> dset = f['mydataset']

The object we obtained isn’t an array, but an HDF5 dataset. Like NumPy arrays, datasets have both a shape and a data type:

>>> dset.shape
(100,)
>>> dset.dtype
dtype('int32')

 

參考資料:

http://docs.h5py.org/en/latest/index.html

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

ASCII 只能儲英文或特殊字符,只占一個字節,一個字節8bit,不能儲中文,所以才出現Unicode

Unicode 不管是中文或英文,都是占二個字節,一個字節8bit

UTF-8 是一種針對Unicode的可變長度字元編碼,英文字符一樣會依照ASCII碼規範,只占一個字節8bit,而中文字符的話,統一就占三個字節了

(1) 在Python 3.x 中,python 直譯器預期的 .py 編碼,預設是 UTF-8,而在 Ubuntu 15.10 中,預設採用的文字編碼也是 UTF-8,

這時在 .py 檔案中撰寫中文,並不會有問題發生,然而,

在 Windows 中,使用記事本編輯文字檔案時,預設的文字編碼是什麼嗎? 在 Windows 中使用記事本編輯文字檔案,預設的編碼是 MS950

所以要加上 # -*- coding: UTF-8 -*-  且儲存成UTF-8格式
忘記加上這一行就在程式使用中文的話,會出現下面的錯誤

SyntaxError: Non-ASCII character '\xe4' in file on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

(2) Python 3.x 中,文字是 str 型態的實例,不過 str 代表的是 Unicode
在 Python 2.x,程式中,文字雖是 str 的實例,然而卻是代表文字資料的位元組序列(Byte sequence )

在 Python 2.x 中,如果想要用 Unicode 來代表文字,也就是想要用 unicode 型態來封裝文字,可以使用 Unicode 字面常量(Unicode literal) 來表示,也就是在文字前置一個 u 符號。

記住: python3 使用unicode

(1) 了解你的環境Default設定,印出目前系統字符編碼

C:\>python
Python 2.7.15 |Anaconda, Inc.| (default, Nov 13 2018, 17:33:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.stdout.encoding
cp437
>>> print sys.getdefaultencoding()
ascii
>>> print sys.getfilesystemencoding()
mbcs

(2) - Environment variable

set PYTHONIOENCODING=UTF-8

在Python3因為字串已經全部統一成 unicode ,所以不必在字符串前加上 u ,這是Python2和Python3的重要差別之一,需要特別注意

stanley 發表在 痞客邦 留言(0) 人氣()

一起學 Python 107 : 五分鐘學會使用 Python 傳送 Line 訊息 在 Raspberry pi 開機啟動提醒

LINE Notify / LINE Login 實作小問題整理-黑暗執行緒

stanley 發表在 痞客邦 留言(0) 人氣()

參考網站 https://steelkiwi.com/blog/working-tcp-sockets/

(1)第一步驟: 建立SOCKET, 而可用參數包括family, type family可輸入 socket.AF_INET or socket.AF_INET6 , 而 type 包括了socket.SOCK_STREAM 

import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

它返回一個socket 物件,而該件有下面的method

  • bind()
    listen()
    accept()
    connect()
    send()
    recv()

bind(), listen() and accept() 是特定為server 使用, 而 connect() 是特定為client 使用, send() and recv() 是兩者皆可使用。

簡單的圖示如下

undefined

(資料來源:http://www.keil.com/pack/doc/mw6/Network/html/NW_Diagrams.png)

Server 例子
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
 
s.listen(1)
conn, addr = s.accept()
while 1: data = conn.recv(1024)
  if not data:
  break
conn.sendall(data)
conn.close()

client 例子
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 50000))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)

所有的method都是 blocking. 意指socket在讀寫資料時程能等待不能做任何事,可能旳解決方案是使用threads, 但使用threads 程式會較長。所以一個解決方式是使用非同步的方式去處理這問題。最主要概念就是讓OS知道現在socket狀態,socket 是在可讀或可寫狀態。所以下面例子在server 上多一個select method

import select, socket, sys, Queue
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server.bind(('localhost', 50000))
server.listen(5)
inputs = [server]
outputs = []
message_queues = {}

while inputs:
    readable, writable, exceptional = select.select(
        inputs, outputs, inputs)
    for s in readable:
        if s is server:
            connection, client_address = s.accept()
            connection.setblocking(0)
            inputs.append(connection)
            message_queues[connection] = Queue.Queue()
        else:
            data = s.recv(1024)
            if data:
                message_queues[s].put(data)
                if s not in outputs:
                    outputs.append(s)
            else:
                if s in outputs:
                    outputs.remove(s)
                inputs.remove(s)
                s.close()
                del message_queues[s]

    for s in writable:
        try:
            next_msg = message_queues[s].get_nowait()
        except Queue.Empty:
            outputs.remove(s)
        else:
            s.send(next_msg)

    for s in exceptional:
        inputs.remove(s)
        if s in outputs:
            outputs.remove(s)
        s.close()
        del message_queues[s]

server.setblocking(0). 設定socket 為nonblocking readable, writable, exceptional = select.select(inputs, outputs, inputs)
blocking and non-blocking socket最主要的不同是sendrecvconnect and accept能夠不做任何事而返回主程式

select.select 要OS求去檢查socekt 是準備去寫或讀或是有例外錯誤,所以需要三個lists去區分那一個socket是預計可讀,可寫,或錯誤。這個method將block程式(除非有設定timeout)直到有一些socket是準備好的,在此時,這個呼叫將返回三個list,說明socket的狀態。

 

stanley 發表在 痞客邦 留言(0) 人氣()

本篇用來記錄Makefile的一些重點筆記,不是教學只有來快速查閱筆記能快速看懂別人的Makefile

#----------------------------------------------------
Makefile的基本組成:

target1: dependencies 
<TAB>command;
target2: dependencies 
<TAB>command;
clean:
<TAB>rm -rf *.o  
#--------------------------------------------------------------
一個簡單的範例:
 
由原始資料:
     gcc main.c foo.c clean.c -I /usr/foo/include -lpthread -L /usr/foo/lib -O3 -ansi -o main
變成Makefile撰寫
 
CC = gcc                            #欲使用的C compiler
CFLAGS = -O3 -ansi         #欲使用的參數
INC = -/usr/foo/include   #include headers的位置
LIB = -/usr/foo/lib            #include libraries的位置
       
main: main.o foo1.o                    
    ${CC} main.o foo1.${CFLAGS} ${INC} ${LIB} -o main
main.o: main.c target.h                    
    ${CC} main.${CFLAGS} ${INC} ${LIB} -lpthread -c  
foo1.o: foo1.c target.h                    
    ${CC} foo1.${CFLAGS} ${INC} ${LIB} -c        
clean:                             
    @rm -rf *.o
#--------------------------------------------------------
如何定義變數 
 
= 是最基本的賦值
:= 會覆蓋變數之前的值
?= 變數為空時才給值,不然則維持之前的值
+= 將值附加到變數的後面

#---------------------------------------------

自動化變數

$@  工作目標檔名
$<    第一個必要條件的檔名.
$^    所有必要條件的檔名, 並以空格隔開這些檔名. (這份清單已經拿掉重複的檔名)
$*    工作目標的主檔名.

#--------------------------------------------
萬用字元(wildcard)

makefile 中所用的萬用字元是 % ,代表所有可能的字串,前後可以接指定的字串來表示某些固定樣式的字串。例如%.c 表示結尾是 .c 的所有字串。
 
#-------------------------------------
內建變數和規則(Implicit Variables and Rules)
 
AR = ar
AS = as
CC = cc
CXX = g++
RM = rm -f
ARFLAGS = rv
CFLAGS =
CXXFLAGS =
 
命令的變數
#-----------------------------------------
• AR 函式庫打包程式。預設命令是“ar”。
• AS 組合語言編譯程序。預設命令是“as”。
• CC C語言編譯程序。預設命令是“cc”。
• CXX C++語言編譯程序。預設命令是“g++”。
• CO 從 RCS檔中擴充檔程式。預設命令是“co”。
• CPP C程式的預處理器(輸出是標準輸出設備)。預設命令是“$(CC) –E”。
• FC Fortran 和 Ratfor 的編譯器和預處理程式。預設命令是“f77”。
• GET 從SCCS檔中擴充檔的程式。預設命令是“get”。
• LEX Lex方法分析器程式(針對於C或Ratfor)。預設命令是“lex”。
• PC Pascal語言編譯程序。預設命令是“pc”。
• YACC Yacc文法分析器(針對於C程式)。預設命令是“yacc”。
• YACCR Yacc文法分析器(針對於Ratfor程式)。預設命令是“yacc –r”。
• MAKEINFO 轉換Texinfo原始檔案(.texi)到Info檔程式。預設命令是“makeinfo”。
• TEX 從TeX原始檔案建立TeX DVI檔的程式。預設命令是“tex”。
• TEXI2DVI 從Texinfo原始檔案建立軍TeX DVI 檔的程式。預設命令是“texi2dvi”。
• WEAVE 轉換Web到TeX的程式。預設命令是“weave”。
• CWEAVE 轉換C Web 到 TeX的程式。預設命令是“cweave”。
• TANGLE 轉換Web到Pascal語言的程式。預設命令是“tangle”。
• CTANGLE 轉換C Web 到 C。預設命令是“ctangle”。
• RM 刪除檔命令。預設命令是“rm –f”。
 

命令參數變數

• ARFLAGS 函式庫打包程式AR命令的參數。預設值是“rv”
• ASFLAGS 組合語言編譯器參數。(當明顯地調用“.s”或“.S”檔案 時)
• CFLAGS C語言編譯器參數。
• CXXFLAGS C++語言編譯器參數。
• COFLAGS RCS命令參數。
• CPPFLAGS C預處理器參數。( C 和 Fortran 編譯器也會用 到)。
• FFLAGS Fortran語言編譯器參數。
• GFLAGS SCCS “get”程式參數。
• LDFLAGS 鏈結器參數。(如:“ld”)
• LFLAGS Lex文法分析器參數。
• PFLAGS Pascal語言編譯器參數。
• RFLAGS Ratfor 程式的Fortran 編譯器參數。
• YFLAGS Yacc文法分析器參數。

#-------------------------------------

Makefile hacks: print the value of any variable

print-%:

       @echo '$*=$($*)'

print-%:

@echo '$*=$($*)'
@echo ' origin = $(origin $*)'
@echo ' flavor = $(flavor $*)'
@echo ' value = $(value $*)

或者

在Makefile新增
print-%: ; @echo $*=$($*) 
then 執行
make print-變數名

#-----------------------------

引用http://maxubuntu.blogspot.tw/2010/02/makefile.html
http://changhoward.blogspot.tw/2009/02/using-gcc-to-create-static-and-shared.html

靜態、共享與動態鏈結函式庫
我們已經知道:輪子不必重複發明 -- 人家寫好的方法我們可以直接拿來用。不過很多時候,這些方法可能因為某些因素,希望提供給別人使用卻又不希望公佈原始碼,這時候編譯成libraries是最好的選擇。

  1. 靜態函式(static libraries)
  2. 靜態函式其實就是將一系列.o檔打包起來,因此她可以直接視為一個巨大的.o檔。打造出一個靜態函式的方法很簡單:
    gcc operator.c -c
    ar crsv liboperator.a operator.o
    或者
    gcc -static operator.c -loperator
    兩種方法皆能產生liboperator.a。假設這個靜態函式在/usr/local/foo/lib/裡,編譯時要與靜態函式作鏈結也很容易:
    gcc main.c /usr/local/foo/lib/liboperator.a -o main
    把靜態函式當成一般的.o檔一起納入binary,也可以像這樣:
    gcc main.c -L /usr/local/foo/lib -loperator -o main
    靜態函式將所有的功能全部打包在一起,因此binary會變得很巨大,但是執行這個程式的所有功能都已滿足,不會再有libraries相依性的問題。但是缺點在於當某些libraries的功能有所更新時,這個程式就必須重新編譯,無法享受到即時更新的優點。通常商業軟體以及嵌入式系統等功能異動較少的程式,會傾向使用靜態函式。




  3.  
  4.  
  5. 共享函式(shared libraries)
  6. 共享函式跟靜態函式的觀念剛好相反,程式在執行時必須能夠找到相依的函式,否則執行時會出現錯誤訊息。製作一個共享函式的方法也很簡單:
    gcc -shared operator.c -o liboperator.so
    或是先編譯出目的檔再進行鏈結:
    gcc -c operator.c
    gcc -shared operator.o -o liboperator.so
    產生出liboperator.so。假設這個共享函式在/usr/local/foo/lib/裡,使用共享函式進行鏈結也很容易:
    gcc main.c /usr/local/foo/lib/liboperator.so -o main
    也可以像這樣:
    gcc main.c -L /usr/local/foo/lib -loperator -o main
    共享函式在程式啟動時期會檢查是否存在。以一個分別鏈結了靜態函式與共享函式的binary而言,執行的結果大有差別。以靜態函式鏈結的main程式可以順利執行,但是假設系統預設尋找函式庫的路徑裡找不到liboperator.so,以共享函式鏈結的main程式則會出現錯誤訊息:
    ./main: error while loading shared libraries: liboperator.so: cannot open shared object file: No such file or directory
    這時解決的方法有四種:
    1. 把liboperator.so複製或是作一個連結到/usr/lib裡。
    2. 修改/etc/ld.so.conf,把/usr/local/foo/lib加進系統libraries的搜尋範圍內。
    3. 設定LD_LIBRARY_PATH變數,累加該路徑進來:
    4. 如果你不是系統管理員,前兩個方法根本沒辦法執行。我們只好自己加到~/.profile裡:
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/foo/lib
    5. 改用靜態函式進行鏈結。
    共享函式經常出現在開放原始碼的linux世界裡,由於使用所有函式皆是共享的,因此許多程式都可以重複利用既有的功能;有新功能或是bug也能簡單的替換掉該函式,所有程式都可以即時享受到這樣的改變,也是最為常見的函式型態。




  7.  
  8.  
  9. 動態函式(dynamic libraries)
  10. 動態函式跟共享函式非常類似,唯一的差別在於程式執行時期並不會去檢查該函式是否存在,而是程式執行到某功能時才進行檢查。這種動態載入的技術最常用在瀏覽器或是大型程式的外掛程式,當有需要用到這個功能時才載入進來。
    製作一個動態函式比較麻煩。
    gcc -c -fPIC operator.c
    gcc -shared operator.o -o liboperator.so
    其中的-fPIC是產生position-independent code,也可以用-fpic。詳細的用法已經超過筆者的理解範圍,撰寫呼叫動態函式的程式碼也需要傳入相關參數。關於更多dynamic libraries的用法請參考這裡
 
參考資料:

                       

 

stanley 發表在 痞客邦 留言(0) 人氣()

在使用microypthon 時heap memory 的管理是很重要的,head memory 的使用率關係到你程式的寫法及可用程式的大小,

所以在程式撰寫方法有三個小技巧,第一是程式中comment的字數不要太多,這些也是會佔有記憶體空間,第二是程式縮排時使用二個空白就好,不要使用tab的方式,畢竟使用晶片不可能像PC有那麼大的記憶體空間可以使用,第三方式是在程式中不要留空白列,留空白列可以讓程式較簡潔易讀但會浪費記憶體空間,

 

這篇文章找了好久,不知在什麼文件看過,之後就一直找不到但我個人

Import gc

gc.collect()

 

mem_info(1)

undefined

Symbol Meaning
. free block
h head block
= tail block
m marked head block
T tuple
L list
D dict
F float
B byte code
M module

參考資料:
https://www.beningo.com/managing-the-heap-space-in-micro-python/
https://docs.micropython.org/en/latest/esp8266/reference/constrained.html

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

2017.11.22(星期三)

這個文件用來記錄ESP-IDF的安裝及使用過程, Espressif IoT Development Framework (esp-idf). 是使用 ESP32 晶片所發展 Internet-of-Things (IoT)應用程式的正式開發架構。

Get Started

需要的材料

  • PC 有Windows, Linux or Mac 作業系統。
  • Download and Install VirtualBox 5.2 & Ubuntu 16.04   (參考http://blog.xuite.net/yh96301/blog/432341564) 
  • Toolchain 建造ESP32的應用程式。
  • ESP-IDF 包括ESP32必須要使用的API。
  • 文字編輯器(e.g. Eclipse)寫C語言 。
  • ESP32 開發板和連到PC的USB cable 

undefined

          ESP32 發展環境三個步驟

  1. 安裝Toolchain。  (參考 https://dl.espressif.com/doc/esp-idf/latest/get-started/windows-setup.html)
  2. 從GitHub得到ESP-IDF。 (參考 https://dl.espressif.com/doc/esp-idf/latest/get-started/index.html#guides)
  3. 設定路徑至ESP-IDF。 (參考 https://dl.espressif.com/doc/esp-idf/latest/get-started/index.html#guides)
  4.  

ESP32 應用程式開發四個步驟

  1. 配置一個專案及程式碼。(參考 https://dl.espressif.com/doc/esp-idf/latest/get-started/index.html#guides)
  2. 編譯專案及連結至應用程式。
  3. 燒錄應用程式至ESP32晶片內。(參考 https://dl.espressif.com/doc/esp-idf/latest/get-started/make-project.html)
  4. 監控及除錯應用程式。

測試程式: Hello World
參考https://exploreembedded.com/wiki/Hello_World_with_ESP32_Explained

  1. /* Hello World Example*/
  2. #include <stdio.h>
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. #include "esp_system.h"
  6.  
  7. void hello_task(void *pvParameter)
  8. {
  9. printf("Hello world!\n");
  10. for (int i = 10; i >= 0; i--) {
  11. printf("Restarting in %d seconds...\n", i);
  12. vTaskDelay(1000 / portTICK_RATE_MS);
  13. }
  14. printf("Restarting now.\n");
  15. fflush(stdout);
  16. esp_restart();
  17. }
  18.  
  19. void app_main()
  20. {
  21. nvs_flash_init();
  22. xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
  23. }

另一個LED  On/Off 程式

  1. #include <stdio.h>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "esp_system.h"
  5. #include "driver/gpio.h"
  6.  
  7. #define BLINK_GPIO 13 
  8.  
  9. void hello_task(void *pvParameter)
  10. { 
  11. while(1)
  12. {
  13. printf("Hello world!\n");
  14. vTaskDelay(100/portTICK_RATE_MS);
  15. }
  16. }
  17.  
  18. void blinky(void *pvParameter)
  19. {
  20.   gpio_pad_select_gpio(BLINK_GPIO); /* Set the GPIO as a push/pull output */
  21. gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
  22. while(1) {   /* Blink off (output low) */
  23. gpio_set_level(BLINK_GPIO, 0);
  24. vTaskDelay(1000/portTICK_RATE_MS);   /* Blink on (output high) */
  25. gpio_set_level(BLINK_GPIO, 1);
  26. vTaskDelay(1000/portTICK_RATE_MS);
  27. }
  28. }
  29.   
  30. void app_main()
  31. {
  32. nvs_flash_init();
  33. xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
  34. xTaskCreate(&blinky, "blinky", 512,NULL,5,NULL );
  35. }

參考資料:

https://dl.espressif.com/doc/esp-idf/latest/index.html
ESP32: Hello World
ESP32 Bluetooth: Using the BTstack library

 

  

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

我們有二種的工作模式

  • Full-step: 
  • Half-step.

 

undefined

Example1 :

   half step control:

import time
import sys
import RPi.GPIO as GPIO

def step_8 (p):
    
    if p==0:
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,0)

    if p==1:
            GPIO.output(5,1)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,0)
             
    if p==2:
            GPIO.output(5,1)
            GPIO.output(6,1)
            GPIO.output(12,0)
            GPIO.output(13,0)
             
    if p==3:          
            GPIO.output(5,0)
            GPIO.output(6,1)
            GPIO.output(12,0)
            GPIO.output(13,0)
    if p==4:
            GPIO.output(5,0)
            GPIO.output(6,1)
            GPIO.output(12,1)
            GPIO.output(13,0)
    if p==5:
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,1)
            GPIO.output(13,0)
    if p==6:
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,1)
            GPIO.output(13,1)
    if p==7:
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,1)
    if p==8:
            GPIO.output(5,1)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,1)

def step_4 (p):
    
    if p==0:
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,0)

    if p==1:
            GPIO.output(5,1)
            GPIO.output(6,1)
            GPIO.output(12,0)
            GPIO.output(13,0)
             
    if p==2:
            GPIO.output(5,0)
            GPIO.output(6,1)
            GPIO.output(12,1)
            GPIO.output(13,0)
             
    if p==3:          
            GPIO.output(5,0)
            GPIO.output(6,0)
            GPIO.output(12,1)
            GPIO.output(13,1)
    if p==4:
            GPIO.output(5,1)
            GPIO.output(6,0)
            GPIO.output(12,0)
            GPIO.output(13,1)
    
用另一種寫法
def steps_8(value):
    print value
    global pas
    if(value<0):
        for i in range (0,abs(value)):
            step_8(pas)
            time.sleep(0.005)
            pas+=1
            if(pas>=9):
               pas=1;
   
    else:
        for i in range (0,abs(value)):
            step_8(pas)
            time.sleep(0.005)
            if(pas==1):
               pas=9;
            pas-=1
    step_8(0)        
def steps_4(value):
    print value
    global pas
    if(value<0):
        for i in range (0,abs(value)):
            step_4(pas)
            time.sleep(0.005)
            pas+=1
            if(pas>=5):
               pas=1;   
    else:
        for i in range (0,abs(value)):
            step_4(pas)
            time.sleep(0.005)
            if(pas==1):
               pas=5;
            pas-=1
    step_4(0)       

主程式

if __name__ == "__main__":             

     GPIO.setmode(GPIO.BCM)
     GPIO.setwarnings(False)
     GPIO.setup(5, GPIO.OUT)
     GPIO.setup(6, GPIO.OUT)
     GPIO.setup(12, GPIO.OUT)
     GPIO.setup(13, GPIO.OUT)
     
     step_4(0)
     pas=1       
     print len(sys.argv)
     if(len(sys.argv)<2):
       print ("Parameter error")
       print ("Usage: sudo python steeper.py val mode")
       print ("val = step number >0clockwise, <0 anticlockwise ")
       print ("mode = 0: 8 phase   2: 1 phase ")
     else:
       st=int(sys.argv[1])
       if(len(sys.argv)==3 and sys.argv[2]=="1"):
          print("8 phase moving")
          steps_8(st)
       else:
          print("4 phase moving")
          steps_4(st)

測試:
python stepper.py -500 0
   #  500 steps anti clockwise full step mode 
python stepper.py 800 1
   #  800 steps clockwise, half-step mode. 
 #----------------------------------

Example2:

Python: stepper.py

#!/usr/bin/python
# Import required libraries
import sys
import time
import RPi.GPIO as GPIO
 
# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)
 
# Define GPIO signals to use
# Physical pins 11,15,16,18
# GPIO17,GPIO22,GPIO23,GPIO24
StepPins = [17,22,23,24]
 
# Set all pins as output
for pin in StepPins:
  print "Setup pins"
  GPIO.setup(pin,GPIO.OUT)
  GPIO.output(pin, False)
 
# Define advanced sequence
# as shown in manufacturers datasheet
Seq = [[1,0,0,1],
       [1,0,0,0],
       [1,1,0,0],
       [0,1,0,0],
       [0,1,1,0],
       [0,0,1,0],
       [0,0,1,1],
       [0,0,0,1]]
        
StepCount = len(Seq)
StepDir = 1 # Set to 1 or 2 for clockwise
            # Set to -1 or -2 for anti-clockwise
 
# Read wait time from command line
if len(sys.argv)>1:
  WaitTime = int(sys.argv[1])/float(1000)
else:
  WaitTime = 10/float(1000)
 
# Initialise variables
StepCounter = 0
 
# Start main loop
while True:
 
  print StepCounter,
  print Seq[StepCounter]
 
  for pin in range(0,4):
    xpin=StepPins[pin]# Get GPIO
    if Seq[StepCounter][pin]!=0:
      print " Enable GPIO %i" %(xpin)
      GPIO.output(xpin, True)
    else:
      GPIO.output(xpin, False)
 
  StepCounter += StepDir
 
  # If we reach the end of the sequence
  # start again
  if (StepCounter>=StepCount):
    StepCounter = 0
  if (StepCounter<0):
    StepCounter = StepCount+StepDir
 
  # Wait before moving on
  time.sleep(WaitTime)

 

python stepper.py 20

測試 20 milliseconds 

#--------------------------------------

Example3 : A Python class to move the stepper motor

where-clock/Stepper.py (Source)

#!/usr/bin/env python

# the 28BJY-48 stepper motor with ULN2003 control board.

from time import sleep
import RPi.GPIO as GPIO

class Motor(object):
    def __init__(self, pins, mode=3):
        """Initialise the motor object.

        pins -- a list of 4 integers referring to the GPIO pins that the IN1, IN2
                IN3 and IN4 pins of the ULN2003 board are wired to
        mode -- the stepping mode to use:
                1: wave drive (not yet implemented)
                2: full step drive
                3: half step drive (default)

        """
        self.P1 = pins[0]
        self.P2 = pins[1]
        self.P3 = pins[2]
        self.P4 = pins[3]
        self.mode = mode
        self.deg_per_step = 5.625 / 64  # for half-step drive (mode 3)
        self.steps_per_rev = int(360 / self.deg_per_step)  # 4096
        self.step_angle = 0  # Assume the way it is pointing is zero degrees
        for p in pins:
            GPIO.setup(p, GPIO.OUT)
            GPIO.output(p, 0)

    def _set_rpm(self, rpm):
        """Set the turn speed in RPM."""
        self._rpm = rpm
        # T is the amount of time to stop between signals
        self._T = (60.0 / rpm) / self.steps_per_rev

   # This means you can set "rpm" as if it is an attribute and 
  # behind the scenes it sets the _T attribute


    rpm = property(lambda self: self._rpm, _set_rpm)

    def move_to(self, angle):
        """Take the shortest route to a particular angle (degrees)."""
        # Make sure there is a 1:1 mapping between angle and stepper angle
        target_step_angle = 8 * (int(angle / self.deg_per_step) / 8)
        steps = target_step_angle - self.step_angle
        steps = (steps % self.steps_per_rev)
        if steps > self.steps_per_rev / 2:
            steps -= self.steps_per_rev
            print "moving " + `steps` + " steps"
            if self.mode == 2:
                self._move_acw_2(-steps / 8)
            else:
                self._move_acw_3(-steps / 8)
        else:
            print "moving " + `steps` + " steps"
            if self.mode == 2:
                self._move_cw_2(steps / 8)
            else:
                self._move_cw_3(steps / 8)
        self.step_angle = target_step_angle

    def __clear(self):
        GPIO.output(self.P1, 0)
        GPIO.output(self.P2, 0)
        GPIO.output(self.P3, 0)
        GPIO.output(self.P4, 0)

    def _move_acw_2(self, big_steps):
        self.__clear()
        for i in range(big_steps):
            GPIO.output(self.P3, 0)
            GPIO.output(self.P1, 1)
            sleep(self._T * 2)
            GPIO.output(self.P2, 0)
            GPIO.output(self.P4, 1)
            sleep(self._T * 2)
            GPIO.output(self.P1, 0)
            GPIO.output(self.P3, 1)
            sleep(self._T * 2)
            GPIO.output(self.P4, 0)
            GPIO.output(self.P2, 1)
            sleep(self._T * 2)

    def _move_cw_2(self, big_steps):
        self.__clear()
        for i in range(big_steps):
            GPIO.output(self.P4, 0)
            GPIO.output(self.P2, 1)
            sleep(self._T * 2)
            GPIO.output(self.P1, 0)
            GPIO.output(self.P3, 1)
            sleep(self._T * 2)
            GPIO.output(self.P2, 0)
            GPIO.output(self.P4, 1)
            sleep(self._T * 2)
            GPIO.output(self.P3, 0)
            GPIO.output(self.P1, 1)
            sleep(self._T * 2)

    def _move_acw_3(self, big_steps):
        self.__clear()
        for i in range(big_steps):
            GPIO.output(self.P1, 0)
            sleep(self._T)
            GPIO.output(self.P3, 1)
            sleep(self._T)
            GPIO.output(self.P4, 0)
            sleep(self._T)
            GPIO.output(self.P2, 1)
            sleep(self._T)
            GPIO.output(self.P3, 0)
            sleep(self._T)
            GPIO.output(self.P1, 1)
            sleep(self._T)
            GPIO.output(self.P2, 0)
            sleep(self._T)
            GPIO.output(self.P4, 1)
            sleep(self._T)

    def _move_cw_3(self, big_steps):
        self.__clear()
        for i in range(big_steps):
            GPIO.output(self.P3, 0)
            sleep(self._T)
            GPIO.output(self.P1, 1)
            sleep(self._T)
            GPIO.output(self.P4, 0)
            sleep(self._T)
            GPIO.output(self.P2, 1)
            sleep(self._T)
            GPIO.output(self.P1, 0)
            sleep(self._T)
            GPIO.output(self.P3, 1)
            sleep(self._T)
            GPIO.output(self.P2, 0)
            sleep(self._T)
            GPIO.output(self.P4, 1)
            sleep(self._T)


if __name__ == "__main__":
    GPIO.setmode(GPIO.BOARD)
    m = Motor([18,22,24,26])
    m.rpm = 5
    print "Pause in seconds: " + `m._T`
    m.move_to(90)
    sleep(1)
    m.move_to(0)
    sleep(1)
    m.mode = 2
    m.move_to(90)
    sleep(1)
    m.move_to(0)
    GPIO.cleanup()

 the motor round by 90 degrees, pause for 1 second, move it back again

#--------------------------------

28BYJ-48 Stepper Motor with ULN2003 driver and Arduino Uno

5 volts DC => about 15+ RPM
12 volts DC => about 25+ RPM.

28BYJ-48 Stepper Motor 特性

Motor Type Unipolar stepper motor
Connection Type 5 Wire Connection (to the motor controller)
Voltage 5-12 Volts DC
Frequency 100 Hz
Step mode Half-step mode recommended (8 step control signal sequence)
Step angle Half-step mode: 8 step control signal sequence (recommended) 5.625 degrees per step / 64 steps per one revolution of the internal motor shaftFull Step mode: 4 step control signal sequence 11.25 degrees per step / 32 steps per one revolution of the internal motor shaft
Gear ratio Manufacturer specifies 64:1. Some patient and diligent people on the Arduino forumshave disassembled the gear train of these little motors and determined that the exact gear ratio is in fact 63.68395:1. My observations confirm their findings. These means that in the recommended half-step mode we will have:64 steps per motor rotation x 63.684 gear ratio = 4076 steps per full revolution (approximately).
Wiring to the ULN2003 controller A (Blue), B (Pink), C (Yellow), D (Orange), E (Red, Mid-Point)
Weight

30g

Model : 28BYJ-48
Rated voltage : 5VDC
Number of Phase : 4
Speed Variation Ratio : 1/64
Stride Angle : 5.625° /64
Frequency : 100Hz
DC resistance : 50Ω±7%(25℃)
Idle In-traction Frequency : > 600Hz
Idle Out-traction Frequency : > 1000Hz
In-traction Torque >34.3mN.m(120Hz)
Self-positioning Torque >34.3mN.m
Friction torque : 600-1200 gf.cm
Pull in torque : 300 gf.cm
Insulated resistance >10MΩ(500V)
Insulated electricity power :600VAC/1mA/1s
Insulation grade :A
Rise in Temperature <40K(120Hz)
Noise <35dB(120Hz,No load,10cm)

 

undefined

參考資料:

https://www.raspberrypi-spy.co.uk/2012/07/stepper-motor-control-in-python/
http://ingeniapp.com/en/stepper-motor-control-with-raspberry-pi/
http://blog.scphillips.com/posts/2012/12/a-python-class-to-move-the-stepper-motor/
http://42bots.com/tutorials/28byj-48-stepper-motor-with-uln2003-driver-and-arduino-uno/

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

Example1: (Station mode)
Python as Server SIde:

 

  1. #!/usr/bin/python             
    prg_n = 'ServerSocketDemo-from-v29'
    #
    # This needs to be running on 'Server' BEFORE starting ESP8266 routine
    #
    import time; import socket; import os; import glob
    port = 1247
    i_cnt=0
    #
    # **** While True Loop ****
    while True:
      s = socket.socket()
      host = socket.gethostname()
      print host, port
      s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # added allow to reuse when re-run
      s.bind(('',port)) # Needed (('',port)) or client never saw it
      s.listen(5)
      c, addr = s.accept()
      # end of setting socket
      #
      print 'c, addr: ', c, addr
      print 'Waiting for data from ESP8266...'
      # it printed... c, addr:  <socket._socketobject object at 0x7ff4d063c670> ('192.168.1.200', 3073)
      print("Connection accepted from " + repr(addr[1]) + "  Server ready for file transfer...\n")
      # it printed... Connection accepted from xxxx  Server ready for file transfer...
      #
      # ACK the client, get filename and open file for writes
      starttime = time.time()    # measure start of ET to get and write file
      c.send("ACK...\n")         # SEND MESSAGE TO CLIENT TO SEND DATA
      #
      tfile = "Server-WIP"
      fobj = open(tfile, "w")
      #
      # Incoming Data, loop until "FILE-EOF", then repeat for additional file(s)
      # get next line...
      client_sent = c.recv(1026)
      #
      while client_sent != 'EOF\n' :
        print client_sent,  # comma supresses a linefeed from printer (string already has a linefeed)
        fobj.write(client_sent)
        client_sent = c.recv(1026)
        #
      ######### HIT EOF\n
      localtime = time.asctime( time.localtime(time.time()) )
      print (localtime)
      E_Time = (time.time() - starttime)
      print "Elapsed Time:  %.2f Seconds" % E_Time
      fobj.write("Server:,,,,,Elapsed Time:  %.2f Seconds" %  E_Time + '\n' )
      fobj.write("Server:,,,,,Program Name:  %s " %prg_n + '\n' )
      fobj.close()
      os.chmod(tfile,0o666) # assign RW- to Owner, Group, Other
      os.rename(tfile, tfile[0:18] + '-' + str(i_cnt))
      i_cnt += 1
      print ('addr[1]: '+repr(addr[1])+' FILE XFER DONE for: '+tfile[0:18]+'-'+ str(i_cnt))
      #
      ### close the socket
      ### a new socket will be created for next upload;
      ### as the client closes its socket after uploads
      ###
      print ('ALL FILES RCVD this session')
      print ('close socket, open new socket and wait for next upload')
      print ('Back to top level # "**** While True Loop ****"\nServer Prog: ' + prg_n)
      s.close()

ESP8266 as Client (Station mode)

  1. prg_n='ESP_SocketDemo.py'
    #
    # NOTE - Server socket must be up and running first
    # This prog uploads the first file found in '/DATA' dir on the ESP8266
    # Must first create '/DATA' and save a text file there
    #
    print(prg_n)
    host='192.168.1.100';port=1247
    my_ssid='ENTER-YOUR_SSID_HERE'
    my_wifi_pw='ENTER_YOUR_NETWORK_PASSWORD_HERE'
    #
    import sys,time,utime,socket,network,machine
    from ntptime import settime
    from machine import Pin
    #
    uos.chdir('/DATA')# must be pre set up on ESP8266, add a text file demo here
    #
    # main code loop below, afer defs...
    #
    def set_WIFI(cntrl):
      i=0;sta_if=network.WLAN(network.STA_IF)
      if cntrl=='ON':
        if not sta_if.isconnected():
          print('conn WiFi')
          sta_if.active(True)
          sta_if.connect(my_ssid,my_wifi_pw)
          while not sta_if.isconnected():
            print(".",end="")
            time.sleep(1);i+=1
            if i>9:return#>>
      else:sta_if.active(False)
      print('NW CFG:',sta_if.ifconfig())
    #
    #
    def upld_data():
      sd=.3 # delay between sends - experiment with this
      df='' # data file name
      p16.high();red_LED=False
      fl=uos.listdir()
      df=fl[0]
      print('fl: ',fl,'   dl:  ',dl) 
      #    
      set_WIFI('ON')
      s=socket.socket();time.sleep(sd)
      try:
        s.connect((host,port))
      except Exception as err:
        print('SockConn-ERR#: ',err)
        return('NOP')#>>
      #
      cmd=s.recv(1024)
      if cmd.startswith('ACK'): # I have Server send 'ACK' on connect
        print('SRV-ACK')
      else:#catch???
        print(cmd+' SRV-NO-ACK')
        s.close();return('NOP')#>>
      #
      print(df)
      s.send(df);time.sleep(sd)
      with open(df,'r') as fobj:
        for line in fobj: # will loop here until end-of-file
          print(line,end='')
          if red_LED == False:#toggle LED during sends
            p16.low();red_LED=True
          else:
            p16.high();red_LED=False
          s.send(line);time.sleep(sd)
      p16.low();red_LED=True
      #
      # following is extra info I send after the file has been read
      s.send('\nprg_n: '+prg_n+', Free MEM:,'+str(gc.mem_free())+'\n')
      time.sleep(sd)
      s.send('fl is: '+str(fl)+'\n')
      time.sleep(sd)
      fl=uos.statvfs('/')
      fl='Tot/Used/Free %d blocks: %d/%d/%d\n' %(fl[0],fl[2],fl[2]-fl[3],fl[3])
      print(fl)
      s.send(fl);time.sleep(sd)
      s.send('EOF\n') # Server will look for EOF message from ESP, finish,
                      # close/open its socket, loop back, wait for next upload
      p16.high()
      return('DONE')#>>
    #
    #END DEF
    #
    while True: # upload every 60 seconds
      if utime.time() % 60 == 0:
        df_status = upld_data()
        print (df_status)
        time.sleep(1)
        gc.collect()
      #
    #

EXample2 : AP mode

ESP8266 As Http Server

  1. import network
    import socket
     
    def log(msg):
        print(msg)
     
     
    def do_connect():
        sta_if = network.WLAN(network.STA_IF)
        if not sta_if.isconnected():
            log('connecting to network...')
            sta_if.active(True)
            sta_if.connect('<SSID>', '<PASSWORD>')
            while not sta_if.isconnected():
                pass
        log('network config:'+str( sta_if.ifconfig()))
     
    def start_myserver():
        log('start server method')
        addr = socket.getaddrinfo('192.168.0.1', 80)[0][-1]
        s = socket.socket()
        s.bind(addr)
        s.listen(1)
        log('listening on'+str( addr))
        while True:
            cl, addr = s.accept()
            log('client connected from'+str(addr))
            cl.send(html)
            cl.close()
     
    #main part
    html = """<!DOCTYPE html>
    <html>
        <head> <title>ESP8266</title> </head>
        <body>
            Hello ESP8266 Server
        </body>
    </html>
    """
     
    do_connect()     # connect to your home router & get a ip address
    start_myserver() # create server according the above get address 
      

ESP8266 As TCP Server


  1. #Start TCP server
  2.  
  3. import network
    import socket
  4.  
  5. def do_connect():
  6.     ap_if = network.WLAN(network.AP_IF)
  7. }

        addr = socket.getaddrinfo('192.168.0.121', 868)[0][-1]
        s = socket.socket()
        s.setblocking(False)
        s.bind(addr)
        s.listen(1)
        while True:
            start = time.ticks_ms()
            socket = (str)(s)
            if len(socket) > 43:
                cl, addr2 = s.accept()
                cl_str = (str)(cl)
                while cl_str[14] == "2":
                    cl_str = (str)(cl)
                data = cl.recv(32)
                print(data)
                cl.close()
                delta = time.ticks_diff(time.ticks_ms(), start)
                print(delta)
     

 

下列測試 1 使用 ESP8266 AP 模式的固定 IP=192.168.4.1 當伺服端位址並綁定 80 埠監聽是否有客戶端連線進來, 有的話就回應 "Hello World" 網頁給遠端客戶.

測試 1 : 簡單的 HTTP 網頁伺服器 

#main.py
import socket
addr=socket.getaddrinfo('192.168.4.1', 80)[0][-1]

s=socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  #設定 socket 位址可重複使用
s.bind(addr)       #Server socket 綁定本身 AP 的網址與 80 埠
s.listen(5)           #設定連線等候佇列最大連線數目為 5
print('listening on', addr)

html='<!DOCTYPE html><html><body>Hello!World</body></html>'

while True:
    cs, addr=s.accept()    #等候連線進來, 接受後傳回與該連線通訊之新 socket 與遠端位址
    print('client connected from', addr)   #輸出遠端網址
    cs.send(html)    #以網頁回應遠端客戶
    cs.close()           #關閉新 socket
s.close()    #關閉 Server socket

將上面程式存成 main.py, 使用 ampy 上傳到 ESP8266 模組 :

D:\test>ampy --port COM4 put main.py

然後開啟 Putty 連線 ESP8266, 按 Ctrl+D 軟開機或插拔 ESP8266 電源重新執行 main.py, 由於進入無窮迴圈之故 REPL 介面最初會無反應.

分別使用筆電或手機以 WiFi 連線 ESP8266 的 AP 基地台 (SSID 是 MicroPython-xxxxxx, 其中 xxxxxx 是 MAC 位址後六碼, 而密碼預設是 micropythoN, 注意最後字元是大寫的 N),

參考資料:
https://forum.micropython.org/viewtopic.php?f=16&t=2804
https://thejeshgn.com/2016/05/05/python-on-esp8266-using-micropython/
https://pydigger.com/pypi/micropython-wifimanager
https://forum.micropython.org/viewtopic.php?t=2512
https://www.tapatalk.com/topic/182447-micropython-forum/2512-wifimanager-script-template
http://yhhuang1966.blogspot.tw/2017/07/micropython-on-esp8266.html

 

stanley 發表在 痞客邦 留言(0) 人氣()

使用Raspberry Pi 的GPIO library 去產生PWM,進而控制DC 直流馬達的工作電壓及速度,是我們經常拿來討論的方法及議題,使用方法很簡單
我們只要使用二個指令即可以設定工作頻率及工作週期,利用這二個指令就可以改變及控制PWM GPIO的工作電壓進而達到控制直流馬達速度的目地。
至於想了解PWM及工作原理及說明設定可以利用Google或參考下面的網站software PWM – How to use it說明,這不是本篇文章要說明的重點。
本篇要思考的重點是要如何設定PWM的工作頻率,很多文章都提到首先先利用這個指令設定頻率GPIO.PWM(GPIO接脚,頻率設定),但問題是我們要設定多少的工作頻率才可以,什麼是最小值和最大值,這個值的大小是否會改變PWM的輸出電壓。

  1. p = GPIO.PWM(2550)    # create an object p for PWM on port 25 at 50 Hertz  
  2.                         # you can have more than one of these, but they need  
  3.                         # different names for each port   
  4.                         # e.g. p1, p2, motor, servo1 etc.  
  5.   
  6. p.start(50)             # start the PWM on 50 percent duty cycle  
  7.                         # duty cycle value can be 0.0 to 100.0%, floats are OK  
  8. p.ChangeDutyCycle(90)   # change the duty cycle to 90%  
  9.   
  10. p.ChangeFrequency(100)  # change the frequency to 100 Hz (floats also work)  
  11.                         # e.g. 100.5, 5.2  
  12.   
  13. p.stop()                # stop the PWM output  
  14.   

我尋找很多資料總是找不到答案,所以才會想要測試看看,我的問題是
(1)PWM頻率的最大值
(2)PWM頻率是否會影響輸出電壓
(3)PWM頻率如何影響散熱

問題一: PWM頻率的最大值
這個問題終於了答案,而且還真是令人想不到的測試結果。這個問題關連到你的硬體設備工作
頻率及使用的語言及library。
當使用Raspberry Pi 時GPIO接脚的反應速度可以多快,

這篇文章是利用Raspberry Pi 來產生方波頻率Benchmarking Raspberry Pi GPIO Speed,其測試結果如下表所示
 

LANGUAGE LIBRARY TESTED / VERSION SQUARE WAVE
Shell /proc/mem access 2015-02-14 2.8 kHz
Shell / gpio utility WiringPi gpio utility 2015-02-15 / 2.25 40 Hz
Python RPi.GPIO 2015-02-15 / 0.5.10 70 kHz
Python wiringpi2 bindings 2015-02-15 / latest github 28 kHz
Ruby wiringpi bindings 2015-02-15 / latest gem (1.1.0) 21 kHz
C Native library 2015-02-15 / latest RaspPi wiki code 22 MHz
C BCM 2835 2015-02-15 / 1.38 5.4 MHz
C wiringPi 2015-02-15 / 2.25 4.1 – 4.6 MHz
Perl BCM 2835 2015-02-15 / 1.9 48 kHz

所以當我們利用Python及RPi.GPIO去產生PWM時最高頻率可以設定至70KHZ,理論上工作頻率愈高,輸出的電壓會愈高但CPU會愈熱。
 

問題二:PWM頻率是否會影響輸出電壓

目前我正在測試,如果有數據資料再來討論結果。

 

 

 

 

 

參考資料:
(1)http://raspi.tv/2013/rpi-gpio-0-5-2a-now-has-software-pwm-how-to-use-it
(2)http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

threads稱做輕量process,他們不需要很多的記憶體空間且一個proces內的數個threads可以共有資料空間和互相溝通。
執行數個threads 相當於同時執行數個不同的程式。

Starting a New Thread

thread.start_new_thread ( function, args[, kwargs] )

Example

#!/usr/bin/python

import thread
import time

# Define a function for the thread
def print_time( threadName, delay):
   count = 0
   while count < 5:
      time.sleep(delay)
      count += 1
      print "%s: %s" % ( threadName, time.ctime(time.time()) )

# Create two threads as follows
try:
   thread.start_new_thread( print_time, ("Thread-1", 2, ) )
   thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
   print "Error: unable to start thread"

while 1:
   pass

結果:

Thread-1: Thu Jan 22 15:42:17 2009
Thread-1: Thu Jan 22 15:42:19 2009
Thread-2: Thu Jan 22 15:42:19 2009
Thread-1: Thu Jan 22 15:42:21 2009
Thread-2: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:23 2009
Thread-1: Thu Jan 22 15:42:25 2009
Thread-2: Thu Jan 22 15:42:27 2009
Thread-2: Thu Jan 22 15:42:31 2009
Thread-2: Thu Jan 22 15:42:35 2009

The Threading Module

在Python 2.4以上使用較新的Threading module 而不使用前面的thread module。Threading module 除了以前的 thread module 方法外更提供額外的方法

  • threading.activeCount(): Returns the number of thread objects that are active.

  • threading.currentThread(): Returns the number of thread objects in the caller's thread control.

  • threading.enumerate(): Returns a list of all thread objects that are currently active.

除了method,,還有thread 類別的implements

  • run(): The run() method is the entry point for a thread.

  • start(): The start() method starts a thread by calling the run method.

  • join([time]): The join() waits for threads to terminate.

  • isAlive(): The isAlive() method checks whether a thread is still executing.

  • getName(): The getName() method returns the name of a thread.

  • setName(): The setName() method sets the name of a thread.

Creating Thread Using Threading Module

  • Define a new subclass of the Thread class.

  • Override the __init__(self [,args]) method to add additional arguments.

  • Then, override the run(self [,args]) method to implement what the thread should do when started.

  • Example

  • #!/usr/bin/python
    
    import threading
    import time
    
    exitFlag = 0
    
    class myThread (threading.Thread):
       def __init__(self, threadID, name, counter):
          threading.Thread.__init__(self)
          self.threadID = threadID
          self.name = name
          self.counter = counter
       def run(self):
          print "Starting " + self.name
          print_time(self.name, self.counter, 5)
          print "Exiting " + self.name
    
    def print_time(threadName, counter, delay):
       while counter:
          if exitFlag:
             threadName.exit()
          time.sleep(delay)
          print "%s: %s" % (threadName, time.ctime(time.time()))
          counter -= 1
    
    # Create new threads
    thread1 = myThread(1, "Thread-1", 1)
    thread2 = myThread(2, "Thread-2", 2)
    
    # Start new Threads
    thread1.start()
    thread2.start()
    
    print "Exiting Main Thread"

    結果:

    Starting Thread-1
    Starting Thread-2
    Exiting Main Thread
    Thread-1: Thu Mar 21 09:10:03 2013
    Thread-1: Thu Mar 21 09:10:04 2013
    Thread-2: Thu Mar 21 09:10:04 2013
    Thread-1: Thu Mar 21 09:10:05 2013
    Thread-1: Thu Mar 21 09:10:06 2013
    Thread-2: Thu Mar 21 09:10:06 2013
    Thread-1: Thu Mar 21 09:10:07 2013
    Exiting Thread-1
    Thread-2: Thu Mar 21 09:10:08 2013
    Thread-2: Thu Mar 21 09:10:10 2013
    Thread-2: Thu Mar 21 09:10:12 2013
    Exiting Thread-2
    
  •  

Synchronizing Threads

使用下面的method 同步thread
(1)Lock() method: returns the new lock.
(2)Racquire(blocking) method :force threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock.If blocking is set to 0, the thread returns immediately with a 0 value if the lock cannot be acquired and with a 1 if the lock was acquired. If blocking is set to 1, the thread blocks and wait for the lock to be released.
(3)release() method of the new lock object is used to release the lock when it is no longer required.

Example

  1. #!/usr/bin/python
    
    import threading
    import time
    
    class myThread (threading.Thread):
       def __init__(self, threadID, name, counter):
          threading.Thread.__init__(self)
          self.threadID = threadID
          self.name = name
          self.counter = counter
       def run(self):
          print "Starting " + self.name
          # Get lock to synchronize threads
          threadLock.acquire()
          print_time(self.name, self.counter, 3)
          # Free lock to release next thread
          threadLock.release()
    
    def print_time(threadName, delay, counter):
       while counter:
          time.sleep(delay)
          print "%s: %s" % (threadName, time.ctime(time.time()))
          counter -= 1
    
    threadLock = threading.Lock()
    threads = []
    
    # Create new threads
    thread1 = myThread(1, "Thread-1", 1)
    thread2 = myThread(2, "Thread-2", 2)
    
    # Start new Threads
    thread1.start()
    thread2.start()
    
    # Add threads to thread list
    threads.append(thread1)
    threads.append(thread2)
    
    # Wait for all threads to complete
    for t in threads:
        t.join()
    print "Exiting Main Thread"

    結果:

    Starting Thread-1
    Starting Thread-2
    Thread-1: Thu Mar 21 09:11:28 2013
    Thread-1: Thu Mar 21 09:11:29 2013
    Thread-1: Thu Mar 21 09:11:30 2013
    Thread-2: Thu Mar 21 09:11:32 2013
    Thread-2: Thu Mar 21 09:11:34 2013
    Thread-2: Thu Mar 21 09:11:36 2013
    Exiting Main Thread
Threading  & GPIO 程式
  1. import RPi.GPIO as GPIO  
  2. GPIO.setmode(GPIO.BCM)  

    import threading
    import time
    import RPi.GPIO as GPIO

    GPIO.setmode(GPIO.BOARD)

    class Button(threading.Thread):
        def __init__(self, channel):
            threading.Thread.__init__(self)
            self._pressed = False
            self.channel = channel
            GPIO.setup(self.channel, GPIO.IN)
            self.deamon = True
            self.start()

        def run(self):
            previous = None
            while 1:
                current = GPIO.input(self.channel)
                time.sleep(0.01)

                if current is False and previous is True:
                    self._pressed = True

                    while self._pressed:
                        time.sleep(0.05)

                previous = current

        def onButtonPress():
            print("btn presdsed")

    button = Button(36)

    while True:
        name = input('Enter a Name:')

        if name.upper() == ('Q'):
            break
        print('hello', name)

        if button.pressed():
            onButtonPress()

RPi.GPIO update and detecting BOTH rising and falling edges

#!/usr/bin/env python2.7
# demo of "BOTH" bi-directional edge detection
 

import RPi.GPIO as GPIO
from time import sleep     # this lets us have a time delay (see line 12)

GPIO.setmode(GPIO.BCM)     # set up BCM GPIO numbering
GPIO.setup(25, GPIO.IN)    # set GPIO25 as input (button)

# Define a threaded callback function to run in another thread when events are detected
def my_callback(channel):
    if GPIO.input(25):     # if port 25 == 1
        print "Rising edge detected on 25"
    else:                  # if port 25 != 1
        print "Falling edge detected on 25"

# when a changing edge is detected on port 25, regardless of whatever
# else is happening in the program, the function my_callback will be run
GPIO.add_event_detect(25, GPIO.BOTH, callback=my_callback)

print "Program will finish after 30 seconds or if you press CTRL+C\n"
print "Make sure you have a button connected, pulled down through 10k resistor"
print "to GND and wired so that when pressed it connects"
print "GPIO port 25 (pin 22) to GND (pin 6) through a ~1k resistor\n"

print "Also put a 100 nF capacitor across your switch for hardware debouncing"
print "This is necessary to see the effect we're looking for"
raw_input("Press Enter when ready\n&gt;")

try:
    print "When pressed, you'll see: Rising Edge detected on 25"
    print "When released, you'll see: Falling Edge detected on 25"
    sleep(30)         # wait 30 seconds
    print "Time's up. Finished!"

finally:                   # this block will run no matter how the try block exits
GPIO.cleanup()         # clean up after yourself

#---------------

我收集下面在Raspberry Pi 中可以使用的中斷處理方式。
在Raspberry Pi 中中斷處理可用下面方式。一種為GPIO中斷處理, 一種為 threaded callback 中斷處理方式
第一種為GPIO中斷處理
  1. #!/usr/bin/env python2.7  
  2. # script by Alex Eames http://RasPi.tv  
  3. # http://RasPi.tv/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3  
  4. import RPi.GPIO as GPIO  
  5. GPIO.setmode(GPIO.BCM)  
  6.   
  7. # GPIO 23 & 17 set up as inputs, pulled up to avoid false detection.  
  8. # Both ports are wired to connect to GND on button press.  
  9. # So we'll be setting up falling edge detection for both  
  10. GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  11. GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  12.   
  13. # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press  
  14. GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
  15.   
  16. # now we'll define two threaded callback functions  
  17. # these will run in another thread when our events are detected  
  18. def my_callback(channel):  
  19.     print "falling edge detected on 17"  
  20.   
  21. def my_callback2(channel):  
  22.     print "falling edge detected on 23"  
  23.   
  24. print "Make sure you have a button connected so that when pressed"  
  25. print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
  26. print "You will also need a second button connected so that when pressed"  
  27. print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)\n"  
  28. print "You will also need a third button connected so that when pressed"  
  29. print "it will connect GPIO port 17 (pin 11) to GND (pin 14)"  
  30. raw_input("Press Enter when ready\n>")  
  31.   
  32. # when a falling edge is detected on port 17, regardless of whatever   
  33. # else is happening in the program, the function my_callback will be run  
  34. GPIO.add_event_detect(17, GPIO.FALLING, callback=my_callback, bouncetime=300)  
  35.   
  36. # when a falling edge is detected on port 23, regardless of whatever   
  37. # else is happening in the program, the function my_callback2 will be run  
  38. # 'bouncetime=300' includes the bounce control written into interrupts2a.py  
  39. GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2, bouncetime=300)  
  40.   
  41. try:  
  42.     print "Waiting for rising edge on port 24"  
  43.     GPIO.wait_for_edge(24, GPIO.RISING)  
  44.     print "Rising edge detected on port 24. Here endeth the third lesson."  
  45.   
  46. except KeyboardInterrupt:  
  47.     GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
  48. GPIO.cleanup()           # clean up GPIO on normal exit  

第二種為 threaded callback 中斷處理

  1. #!/usr/bin/env python2.7  
  2. # script by Alex Eames http://RasPi.tv  
  3.   
  4. import RPi.GPIO as GPIO  
  5. GPIO.setmode(GPIO.BCM)  
  6.   
  7. # GPIO 23 & 24 set up as inputs. One pulled up, the other down.  
  8. # 23 will go to GND when button pressed and 24 will go to 3V3 (3.3V)  
  9. # this enables us to demonstrate both rising and falling edge detection  
  10. GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  11. GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
  12.   
  13. # now we'll define the threaded callback function  
  14. # this will run in another thread when our event is detected  
  15. def my_callback(channel):  
  16.     print "Rising edge detected on port 24 - even though, in the main thread,"  
  17.     print "we are still waiting for a falling edge - how cool?\n"  
  18.   
  19. print "Make sure you have a button connected so that when pressed"  
  20. print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
  21. print "You will also need a second button connected so that when pressed"  
  22. print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)"  
  23. raw_input("Press Enter when ready\n>")  
  24.   
  25. # The GPIO.add_event_detect() line below set things up so that  
  26. # when a rising edge is detected on port 24, regardless of whatever   
  27. # else is happening in the program, the function "my_callback" will be run  
  28. # It will happen even while the program is waiting for  
  29. # a falling edge on the other button.  
  30. GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback)  
  31.   
  32. try:  
  33.     print "Waiting for falling edge on port 23"  
  34.     GPIO.wait_for_edge(23, GPIO.FALLING)  
  35.     print "Falling edge detected. Here endeth the second lesson."  
  36.   
  37. except KeyboardInterrupt:  
  38.     GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
  39. GPIO.cleanup()           # clean up GPIO on normal exit  

<3>為Multiple threaded callback 中斷處理

  1. # script by Alex Eames http://RasPi.tv  
  2. # http://RasPi.tv/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3  
  3. import RPi.GPIO as GPIO  
  4. GPIO.setmode(GPIO.BCM)  
  5.   
  6. # GPIO 23 & 17 set up as inputs, pulled up to avoid false detection.  
  7. # Both ports are wired to connect to GND on button press.  
  8. # So we'll be setting up falling edge detection for both  
  9. GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  10. GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  11.   
  12. # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press  
  13. GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
  14.   
  15. # now we'll define two threaded callback functions  
  16. # these will run in another thread when our events are detected  
  17. def my_callback(channel):  
  18.     print "falling edge detected on 17"  
  19.   
  20. def my_callback2(channel):  
  21.     print "falling edge detected on 23"  
  22.   
  23. print "Make sure you have a button connected so that when pressed"  
  24. print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
  25. print "You will also need a second button connected so that when pressed"  
  26. print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)\n"  
  27. print "You will also need a third button connected so that when pressed"  
  28. print "it will connect GPIO port 17 (pin 11) to GND (pin 14)"  
  29. raw_input("Press Enter when ready\n>")  
  30.   
  31. # when a falling edge is detected on port 17, regardless of whatever   
  32. # else is happening in the program, the function my_callback will be run  
  33. GPIO.add_event_detect(17, GPIO.FALLING, callback=my_callback, bouncetime=300)  
  34.   
  35. # when a falling edge is detected on port 23, regardless of whatever   
  36. # else is happening in the program, the function my_callback2 will be run  
  37. # 'bouncetime=300' includes the bounce control written into interrupts2a.py  
  38. GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2, bouncetime=300)  
  39.   
  40. try:  
  41.     print "Waiting for rising edge on port 24"  
  42.     GPIO.wait_for_edge(24, GPIO.RISING)  
  43.     print "Rising edge detected on port 24. Here endeth the third lesson."  
  44.   
  45. except KeyboardInterrupt:  
  46.     GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
  47. GPIO.cleanup()           # clean up GPIO on normal exit  

最後一個很實用的程式應用架構,可以參考的是Pooling Threads
Pooling Threads
有時侯我們建立太多 thread 時可能會造成系統(或程式)效能變差,
例如說我們只想建立兩個 threads,可是我們有十件工作要做,那麼我們就可以用排程的概念來實做。
在程式的一開始先把兩個 thread 建好,然後利用 python 的 Queue module去做pool的動作,把十件工作的資料都 put 進 Queue。
在 thread function 裡面會去 get Queue 的資料,只要 get 到thread 就會開始工作。

  1. #!/usr/bin/python
    #-*- coding:utf-8 -*-

    from threading import *
    import Queue
    import time

    class MyThread(Thread):
        def ___init__(self, condition):
            Thread.__init__(self)
            self.cond = condition

        def run(self):
            print '{0} start\r\n'.format(self.getName())
            global cnt
            while (True):
                id = threadPool.get()
                if id != None:
                self.cond.acquire()
                print '{0}_{1}'.format(self.getName(), id)
                for x in xrange(101):
                   cnt += x
                   time.sleep(2) 
                print 'cnt = {0}\r\n'.format(cnt)
                cnt = 0 
                self.cond.release()
                threadPool.task_done()


    threadPool = Queue.Queue(0)
    condition = Condition()
    cnt = 0
    for i in xrange(2):
        MyThread(condition).start()

    for i in xrange(10): 
        threadPool.put(i)

    threadPool.join()
    print 'done'


     
  1. 在 thread function 最後呼叫 task_done() 是為了讓 Queue 知道這一個工作已經完成,
    是給 Queue.join() 作為參考。

    如果這些工作會存取到相同的資源,
    還是記得要用 Lock 保護。
     

 

 

資料來源:

(1) http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3
(2) http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-2
(3)http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio
(4)http://robsraspberrypi.blogspot.tw/2016/01/raspberry-pi-python-threading.html
(5)https://www.tutorialspoint.com/python/python_multithreading.htm
(6)http://robsraspberrypi.blogspot.tw/2016/01/raspberry-pi-python-threading.html
(7)RPi.GPIO update and detecting BOTH rising and falling edges
(8)http://raspi.tv/rpi-gpio
(9)http://skiesblog.blogspot.tw/2010/01/threading-in-python.html

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

(1) 超音波測距離-使用python

參考資料: Raspberry Pi 筆記:超音波測距離

[材料]

• Raspberry Pi 主板 x1
• US-100超音波模組 x1
• 連接線  x4

[基礎知識:超音波測距]

超音波測距的方式是發射一個電波,當電波遇到物體反射回來,再被測距儀偵測到反射電波,利用來回時間與音波的速度算出距離,計算公式如下:
距離=(音波發射與接收時間差 * 聲音速度(340M/S))/2;
聲音的速度,在一般空氣中約為每秒340公尺,因來回時間要將距離除以二,才是單程的距離。實際的聲音速度決定於好幾個環境因素,其中一個是溫度,計算時需將環境因素考慮在內,才能更精確計算距離。
US-100這個型號,根據規格文件,這個模組最遠可測得2公分~4.5公尺, 輸入電壓大約 2.4V ~ 5.5V,其偵測廣度大約是15度。這個模組具有溫度感測,距離值已經溫度調校,無需再根據環境溫度對超音波聲速進行校正。

[線路連接與電路圖](圖片以HC-SR04替代)

• US-100 VCC接pin2(+5V),GND接pin6(GND)
• US-100 Trig/TX接Pin16(GPIO23),Echo/RX接Pin18(GPIO24)

undefined
[程式碼]

import RPi.GPIO as GPIO
import time
trigger_pin = 23
echo_pin = 24

GPIO.setmode(GPIO.BCM)
GPIO.setup(trigger_pin, GPIO.OUT)
GPIO.setup(echo_pin, GPIO.IN)

def send_trigger_pulse():
    GPIO.output(trigger_pin, True)
    time.sleep(0.001)
    GPIO.output(trigger_pin, False)

def wait_for_echo(value, timeout):
    count = timeout
    while GPIO.input(echo_pin) != value and count > 0:
        count = count - 1

def get_distance():
    send_trigger_pulse()
    wait_for_echo(True, 5000)
    start = time.time()
    wait_for_echo(False, 5000)
    finish = time.time()
    pulse_len = finish - start
    distance_cm = pulse_len * 340 *100 /2
    distance_in = distance_cm / 2.5
    return (distance_cm, distance_in)

while True:
    print("cm=%f\tinches=%f" % get_distance())
    time.sleep(1)

<2>使用霍爾效應感測器測量車輛速度

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

pulse = 0
distance = 0
rpm = 0.00
speed = 0.00
wheel_c = 20
hall = 18
elapse = 0.00

start = time.time()

GPIO.setup(hall, GPIO.IN, pull_up_down = GPIO.PUD_UP)


def get_rpm():
    return rpm

def get_speed():
    return speed

def get_distance():
    return distance

def get_elapse():
    return elapse

def get_pulse(number):
    global elapse,distance,start,pulse,speed,rpm,multiplier
    cycle = 0
    pulse+=1
    cycle+=1
    if pulse > 0:
        elapse = time.time() - start
        pulse -=1
    if cycle > 0:
        distance += wheel_c
        cycle -= 1

    speed = (wheel_c*multiplier)/100000
    rpm = 1/elapse *60

    start = time.time()

try:

    time.sleep(1)

    GPIO.add_event_detect(hall,GPIO.FALLING,callback = get_pulse,bouncetime=20)
    while True:
    print('rpm:{0:.2f} speed:{1:.2f} distance:{2} elapse:{3:.4f}'.format(rpm,speed,distance,elapse))
        time.sleep(0.1) #to reduce CPU load, print every 100 milliseconds


except KeyboardInterrupt:
    print('You have pressed Ctrl+C! How dare you stopped this beautiful thing?!')
    GPIO.cleanup()

Speed sensor calculation using Python
How to use Python to measure speed of bike like a digital speedometer, using a Raspberry Pi?
How To Use A Hall Effect Sensor With The Raspberry Pi
Getting feedback from a hall sensor with Raspberry Pi
https://www.sunfounder.com/learn/sensor-kit-v2-0-for-b/lesson-17-hall-sensor-sensor-kit-v2-0-for-b.html
http://www.14core.com/wiring-the-3144-hall-effect-sensor-with-raspberry-pi/
https://stackoverflow.com/questions/40738776/how-to-use-python-to-measure-speed-of-bike-like-a-digital-speedometer-using-a-r

 

<3>How to connect your phone to your ESP8266 module
Control ESP8266 Over the Internet (from Anywhere)


 

 

 

 

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

第一個簡單程式

First approaches to image processing: load and display an image

import cv2 as cv

img = cv.imread('logos.jpg')  # imread () method reads the file (a compressed format such as JPG) and translate it into a data structure 
                                                #
 made of numerical  matrix corresponding to color gradations and position.
cv.imshow('Image', img)       # imshow() method to create a window with the image loaded in the variable img
cv.waitKey(0)                       # waitKey() method starts the display of a window and also allows you to control the waiting time of the program before 
                                                     continuing with the next command

 

Working with images 

import cv2 ascv
 
img=cv.imread('logos.jpg')
b,r,g=cv.split(img)
img2=cv.merge((b,g,r))
cv.imshow('Image',img)
cv.imshow('Image2',img2)
cv.waitKey(0)
cv.destroyAllWindows()

After loading the image Decompose in the three RGB channels. You can do this easily by using the split() method.
Now reassemble the three channels, but changing the order, for example by exchanging the red channel with the green channel.
You can easily make recombination using the merge() method.
The destroyWindow() method allows you to close the desired window (could be several open) by specifying as argument the name of the window which in your case is “Image”.

Save the new image

cv.imwrite('newlogos.png',img2)

 

Accessing and Modifying pixel values

You can access a pixel value by its row and column coordinates. 
For BGR image, it returns an array of Blue, Green, Red values.
For grayscale image, just corresponding intensity is returned.

px = img[100,100] print px [157 166 200] # accessing only blue pixel blue = img[100,100,0] print blue 157

You can modify the pixel values the same way.
img[100,100] = [255,255,255]
print img[100,100]
[255 255 255]

Accessing Image Properties

Image properties include number of rows, columns and channels, type of image data, number of pixels etc.
Shape of image is accessed by img.shape. It returns a tuple of number of rows, columns and channels (if image is color):

Example : 
  rows,cols,channels = img2.shape

 

print img.shape
(342, 548, 3) 

Note

If image is grayscale, tuple returned contains only number of rows and columns. So it is a good method to check if loaded image is grayscale or color image.

 

Total number of pixels is accessed by img.size:

>>> print img.size
562248

Image datatype is obtained by img.dtype:

>>> print img.dtype
uint8
 

Image ROI

Sometimes, you will have to play with certain region of images. ROI is again obtained using Numpy indexing.
Here I am selecting the ball and copying it to another region in the image:
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball


Splitting and Merging Image Channels

The B,G,R channels of an image can be split into their individual planes when needed. Then, the individual channels can be merged back together to form a BGR image again. This can be performed by:

 

b,g,r = cv2.split(img)
img = cv2.merge((b,g,r))

 

Or

b=img[:,:,0]

Suppose, you want to make all the red pixels to zero, you need not split like this and put it equal to zero. You can simply use Numpy indexing which is faster. 
img[:,:,2] = 0

 

Making Borders for Images (Padding)

If you want to create a border around the image, something like a photo frame, you can use cv2.copyMakeBorder() function. But it has more applications for convolution operation, zero padding etc. This function takes following arguments:

  • src - input image
  • topbottomleftright - border width in number of pixels in corresponding directions
  • borderType - Flag defining what kind of border to be added. It can be following types:
    • cv2.BORDER_CONSTANT - Adds a constant colored border. The value should be given as next argument.
    • cv2.BORDER_REFLECT - Border will be mirror reflection of the border elements, like this : fedcba|abcdefgh|hgfedcb
    • cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT - Same as above, but with a slight change, like this : gfedcb|abcdefgh|gfedcba
    • cv2.BORDER_REPLICATE - Last element is replicated throughout, like this: aaaaaa|abcdefgh|hhhhhhh
    • cv2.BORDER_WRAP - Can’t explain, it will look like this : cdefgh|abcdefgh|abcdefg
  • value - Color of border if border type is cv2.BORDER_CONSTANT

Below is a sample code demonstrating all these border types for better understanding:

import cv2
import numpy as np
from matplotlib import pyplot as plt

BLUE = [255,0,0]

img1 = cv2.imread('opencv_logo.png')

replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)

plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')

plt.show()


Arithmetic Operations on Images

Goal

  • Learn several arithmetic operations on images like addition, subtraction, bitwise operations etc.
  • You will learn these functions : cv2.add()cv2.addWeighted() etc.

Image Addition

You can add two images by OpenCV function, cv2.add() or simply by numpy operation, res = img1 + img2. Both images should be of same depth and type, or second image can just be a scalar value.

 

Image Blending

This is also image addition, but different weights are given to images so that it gives a feeling of blending or transparency. Images are added as per the equation below:

cv2.addWeighted() applies following equation on the image.

More info .... 
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_core/py_image_arithmetics/py_image_arithmetics.html

Bitwise Operations

This includes bitwise AND, OR, NOT and XOR operations. They will be highly useful while extracting any part of the image , defining and working with non-rectangular ROI etc.

bitwise_not,bitwise_and
資料來源:

<1> OpenCV and Python – Load, view and save images on Raspberry-Introduction
<2> https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_core/py_basic_ops/py_basic_ops.html#basic-ops
<3> OpenCV教學(62)

 

stanley 發表在 痞客邦 留言(0) 人氣()

(1) 開啓下載網頁 https://pypi.python.org/pypi/opencv-python

(2) pip install opencv-python

(3) 將會自動 Import the opencv package & numpy

Installing collected packages: numpy, opencv-python
Found existing installation: numpy 1.8.1
DEPRECATION: Uninstalling a distutils installed project (numpy) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project. 
Uninstalling numpy-1.8.1:
Successfully uninstalled numpy-1.8.1
Successfully installed numpy-1.13.3 opencv-python-3.3.0.10

(4)測試模組

c:\python> python  

Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print cv2.__version__
3.3.0
>>> import numpy
>>> print numpy.__version__
1.13.3
>>>

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

(1) 儲存檔案

with open("Output.txt","w")as text_file:

text_file.write("Purchase Amount: {0}".format(TotalAmount)) 

或 > = python2.7 可以使用 {} 代替 {0} 

with open("Output.txt","w")as text_file:

print("Purchase Amount: {}".format(TotalAmount))

(2) 字串的運算: 字串資料也支援下列幾種運算方式
(2.1)  字串相加 : 兩個字串資料作相加(+)的運算

x = 'Hello, '
y = 'World'
print x+y

這段程式碼會印出 Hello, World

(2.2)產生重複字串

字串資料可以與整數進行 * 的運算,這表示要將字串重複幾次:

x = 'Cat'
print x * 3

這樣螢幕會輸出 CatCatCat

(2.3)取出字串部份內容

想要取出字串部份的內容,不管是單一字元,或是一段範圍的字串,可以使用 [] 運算子來操作:

x = 'Hello, World.'
print x[7]
print hello[0:6]

 這段程式碼會分別在螢幕上印出 "W" 及 "Hello,"

(2.4)計算字串長度

如果要計算字串的長度,直接使用 len() 函式就可以了。

+

 

x = 'Hello, World.'
print len(x)

就會在螢幕上印出 13

 

 

(3)使用 List 資料

 

List 資料型態可以用來表示或處理排列在一起的資料,在 Python 裡是使用中括號( [ 及 ] )包起來表示,而 List 裡的資料可以是任何資料型態:記住,List 資料的索引是*從0開始**

 

a = [1, 3, 'abc', 7, "xyz"]
print a[3]

 

 

螢幕上印出: 7 

(3.1)選取某個元素

單一索引值取出 List 資料中的某一份資料

(3.2)選取一段範圍

除了使用單一索引值取得 List 中單一元素,也可以設定範圍取出一段部份資料,如:

print a[1:3]

螢幕上印出: [3, 'abc']

(4)Dictionary

建立一個 Dictionary 物件

d = {'python': 'Large constricting snakes.', 'ruby': 'A precious stone that is a red corundum.'}

 使用 [] 這個運算子的時候,我們就可以拿到它的 Value 了 

 

print d['python']

 

則會印出

 

Large constricting snakes.

 

(4.1)取得 Dictionary 物件中 Key 的個數

 

print len(d)

 

則會印出:2

(4.2)新增或修改一筆資料

 

d['game'] = 'Activity engaged in for diversion or amusement.'
print d

 

(4.3)刪除一筆資料

del d['game']
print d

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

在Web的世界中, client 和 server 兩者之間最常做的動作就是 Request-Response(要求-回應),用戶端送一個要求(Request),而伺服器回應訊息(Response)。
所以我們要了解HTTP Request的方法。HTTP Request 的方法有二種: GET and  POST,這二者之間有何差別。

HTTP Request 方法二種:


(1) Get 方法:當表單 Submit 之後瀏覽器的網址就變成 "/test/demo_form.php/?id=010101",瀏覽器會自動將表單內容轉為 Query String 加在 URL 進行連線。

客戶端傳送形式: <form action="接收資料的程式" method="get">

伺服器接收形式:這個鍵值配對會被存入request.GET中,用request.GET['變數名']可以得到值 

  • GET requests 會儲存在快取區。
  • GET requests 會儲在客戶端瀏覽器的歷史區。
  • GET requests 可以被標示。
  • GET requests 不要使用在敏感性資料。
  • GET requests 有長度限制。
  • GET requests 應該僅使用在擷取資料。
  • GET requests 資料會顯示在URL上。
  • GET requests 網址會帶有 HTML Form 表單的參數與資料。
  • GET requests 只接受ASCII字符。

(2) Post 方法:POST 是將表單資料放在 message-body 進行傳送。

客戶端傳送形式<form action="接收資料的程式" method="post">

伺服器接收形式:這個鍵值配對會被存入request.POST中,用request.POST['變數名']可以得到值 

  • POST requests 不會儲存在快取區
  • POST requests 不會儲在客戶端瀏覽器的歷史區
  • POST requests 不可以被標示。
  • POST requests 沒有長度限制。
  • POST requests 資料傳遞時,網址並不會改變。
  • POST requests 字符類型没有限制。

注意: GET 的URL 會顯示出Query 字串,而Query 字串內包含變數名/資料,所以會比較不安全,建議含有密碼的資訊不要使用這種方法。

回Django Web 程式設計主目錄

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

這篇文章中我們將說明如何在Templates 中如何與Javascript,CSS、JQuery互動。 一個網頁除了後端資料庫外,我想另一個最重要的是網頁前端外觀的呈現,而網頁前端的工作則要利用Javascript,CSS、JQuery等語言去處理,因此我需要在Templates的使用上多記錄一些東西,另外是否要學習Templates language。
我經常看這個圖然後思考一些資料流傳送的問題

(1) 在 Views 中的資料如何傳送至Templates ? 
(2) 在 Views 中如何使用Models 的資料 ? 
(3) 在 Templates 如何使用Javascript 及 JQuery ? 
以上這些問題都在章節都有答案。但還有下面問題,Templates 是前端程式,而Views 是後端程式
(4) 在 Templates中如何宣告變數及設定變數值初值 ?
答案: 有二種方法
(1)用with template tag 方法 
  例子1 : 設定初值

{% with name="World" greeting="Hello" %}
<html>
<div>{{ greeting }} {{name}}!</div>
</html>
{% endwith %}

   例子2 : 將Models 中的值帶進來

{%with restaurant_id=restaurant.id %}
... use restaurant_id in this template section ...
{% endwith %}

 (2) 

{% my_var = "My String" %}
然後使用
<h1>{% trans my_var %}</h1>
或者
{% trans "my string" as my_var %}
{{ my_var }} {# 你可以使用my_var 變數 #}

 (5) Templates 中的變數值可以傳送至Views 嗎?
答案: 有四種方法

1. Post

傳送內容有值的form

# 在views.py 中經由
    request.POST.get('value')

2. Query Parameters

使用 //localhost:8000/?id=123

# 在views.py 中經由
 request.GET.get('id')

3. From the URL (See here for example)

使用 //localhost:8000/12/results/

# 在urls.py 中經由
  urlpatterns = patterns(... url(r'^(?P<question_id>\d+)/results/$', views.results, name='results'),...)

 # 在 views 中得到 (question_id)

def detail(request, question_id):
  ...
returnHttpResponse("blahblah")

4. Session (使用 cookie)

Downside of using session is you would have had to pass it to the view or set it earlier.

https://docs.djangoproject.com/en/1.7/topics/http/sessions/

# views.py
# 設定session變數
    request.session['uid']=123456  
# 擷取session變數
var= request.session.get['uid']

(6)使用JQuery 傳送變數值至Views(使用GET)

在urls.py 中新增
url(r'^list/$', list),
url(r'^list_ret/$', list_ret)

 在views.py 中新增

def list(request):
     return render(request, 'list.html')

def list_ret(request):
list_ret_data = request.GET.get('list')
     return render(request, 'list_ret.html')

 新增list.html 

{% load staticfiles %}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
    <head>
     <title>Django/jQuery AJAX</title>
      <link rel="stylesheet" type="text/css" href="{% static 'style.css' %}" />

    <script src="{% static "jquery-3.2.1.js" %}"></script>
      <script src="{% static "jquery-ui-1.12.1.zip" %}"></script>
      <! ------- must care the path --------------------------------------------!>         
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"> </script>
<script type="text/javascript">             

        function list_Btn() {
         var list = $('#right').text();
               alert(list);
                            
         $.ajax({
           url: '/list_ret/',          
type: 'get',          
           data :{'list' : list},
           success: function(msg) {
             alert('結果'+msg);
           },
           error: function(data){
            alert('status:'+data.status); // the status code
            alert(data.responseJSON.error); // the message
           }
         });       
       }      
</script>
 </head>  

 <div id = 'right' style="width: 25%; float:right;text-align:left;font-size:20px;">
資料傳送開始
     <br>  
     <input id = 'song_Btn' type ="button" value="傳送" onClick="list_Btn()"></input>
  </div>  

</html>

 新增list_ret.html 

傳送資料回覆(任何傳送前端內容)
{{list_ret_data}}

 

這是一個最簡單的一個範例,我們可以在 class list_ret 中接收到前端所傳送過來的所有資料,然後我們就可以在後端做資料庫處理,作檔案操縱,作企業邏輯運算,作任何在後端可以做的事,運算完後將結果放入一個中間網頁再回傳到原來呼叫的網頁,如此就可以不用改變前端網頁內容而做到後端處理的非同步網頁處理方式。

<6> 從Views 傳送一個dict 去Templates 

views 

def main(request):
    ord_dict['2015-06-20']={}
    ord_dict['2015-06-20']['a']='1'
    ord_dict['2015-06-20']['b']='2'
    ord_dict['2015-06-21']={}
    ord_dict['2015-06-21']['a']='10'
    ord_dict['2015-06-21']['b']='20'

return render(request, 'list.html',locals())

 Templates(由小排至大)

<table>
{%for key, value in context.items.items|dictsort:"0.lower" %}
<tr> <td>{{ key }}</td>
<td>{{ value.a }}</td>
<td>{{ value.b }}</td>
</tr>
{% endfor %}
</table>

<6> 從Views 傳送一個list 去Templates 

 views  

def main(request):

return render(request, 'list.html',locals())

  Templates 

<table>

<tr> <td>{{ key }}</td>

</tr>
{% endfor %}
</table>

 <7> 從Views 傳送一個含有中文字的變數至Templates 

在views  第一行寫# -*- coding: utf-8 -*-,並且檔案儲存格式存成utf-8格式

# -*- coding: utf-8 -*- 

def
main(request):
x1 = "中文"
return render(request, 'list.html',locals())

  Templates 檔案儲存格式存成utf-8格式

{{X1}}

 

 

 

回Django Web 程式設計主目錄


 

 

  

     

 

 

 

 

 




 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

 

 2017.08.28 

篇文章中我們將說明在Django中如何使用Javascript,CSS、JQuery。
一個網頁除了後端資料庫外,我
想另一個最重要的是網頁前端外觀的呈現,而網頁前端的工作則要利用Javascript,CSS、JQuery等語言去處理,因此這篇是很重要的參考文章。至於Javascript,CSS、JQuery等語言設計可能要另外參考資料了。

 

 在 settings 中新增

# Add these new lines
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

 

(1)在專案目錄下新增一個staic 資料夾,與目錄須要配合上面的路徑設定,我們是要將js檔案放在os.path.join(BASE_DIR, 'static')
所以放在與 /tempates 同層次的目錄,這部份的設定是否有錯可參考http server的status 返回值是否顯示200或304,如顥示200或304表示路徑及檔案己成功找到並載入,如出現404則表示
建錯目錄或找不到檔案。
(2)使用JavaScript不需要另外載入程式庫只要宣告就可以使用。
(3)JQuery程式庫可用二種方式載入,一種為檔案方式,一種為URL方式。
(4)檔案形式可於https://jquery.com/download/my 下載,下載.js 檔,min.js或壓縮檔皆可以。下載後放在/static資料夾。
(5)URL方式請檔案內設定URL路徑即可。

我們以之前的list.htm為例,在網頁內容內新增

{% load staticfiles %}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
    <head>
     <title>Django/jQuery AJAX</title>      
      <link rel="stylesheet" type="text/css" href="{% static 'style.css' %}" />
      <script src="{% static "jquery-3.2.1.js" %}"></script>
      <script src="{% static "jquery-ui-1.12.1.zip" %}"></script>
      <! ------- must care the path --------------------------------------------!>         
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"> </script>

      <script type="text/javascript">
       function nothing() { 
        alert("查無任何資料,請重新查詢");
       }
      $( document ).ready(function() {
           alert("Hello Jquery");
      $("#msg").click(function(){
         alert("Hello DIV");
      });    
      });
      </script>

     
    </head>
    <body>資料表內容<br>
     {% for item in datas %}
      <tr>
        <td>{{ item.song_name }}</td>       
        <td>{{ item.songer }}</td>
      </tr><br>
     {% endfor %}
     <input type ="button" value="submit" onClick="nothing()"></input> <br>
     <div id='msg' style="text-align:center;font-size:20px;">
       I am DIV, please click me <br>                  
     </div>    
</html>

如此Javascript 及JQuery 就可以在前端正常工作了。

回Django Web 程式設計主目錄

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

1 23
Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼