레이블이 BusPirate인 게시물을 표시합니다. 모든 게시물 표시
레이블이 BusPirate인 게시물을 표시합니다. 모든 게시물 표시

2017년 5월 12일 금요일

BusPirate를 파이선으로 제어하기

수년간 AVR-ISP mkII를 사용해 ATMEL AVR 마이크로 컨트롤러를 프로그래밍 해 오다가, 오늘 처음으로 Bus Pirate를 사용해 보았다. 이 작은 보드는 단순히 마이컴 프로그래머가 아니고 기본적으로 마이컴 주변장치와의 시리얼 인터페이스이다. 보드를 USB에 연결하면 커맨드라인 인터페이스를 가지고 있는 시리얼 포트로 보이는데 이를 통해 핀의 on/off, 전압 측정 뿐 아니고 I2C, SPI, UART 심지어 HD44780 시리즈 LCD 프로토콜까지도 양방향으로 사용할 수 있도록 네이티브하게 지원한다.
HyperTerminal을 사용해 BusPirate와 직접 인터페이스 할 수도 있지만 TeraTerm을 사용하는걸 권장한다. 작은 회로에 전원을 공급할 수 있게 3.3V와 5V 전원을 공급할 수 있고, 만일 전류를 과도하게 소비하면 자동으로 전원 공급을 끊어버린다.
BusPirate는 $30 이하로 구할 수 있는 매우 훌륭한 개발툴이다. 또한 AVRDUDE를 통해 네이티브하게 AVR 프로그래머로 동작할 수 있다. 어셈블리 코드를 작성할수도 있지만 편의성을 위해 거의 항상 C로 프로그램을 작성한다. 나의 레퍼런스 (또는 유사한 작업을 하길 원하는 다른 사람의 레퍼런스)를 위해 윈도우에서 BusPirate로 AVR 마이컴을 프로그래밍 하기 위해 사용하는 가장 쉬운 방법을 포스팅한다. 또한 BusPirate와 연결한 다름 간단한 명령들을 실행하는 파이선 스크립트(파워 서플라이를 켜고 프로그래밍이 끝나면 곧바로 VCC의 전압을 리포팅)를 작성했다.

물론 파이선으로 BusPirate와 인터액션 할 수 있게 해 주는 팬시한 패키지도 있지만 내 방법의 장점은 네이티브 파이선 라이브러리에서 실행된다는 것이다. 이렇게 사용하고 싶으면 WinAVR과 python 3.1을 설치하면 된다. 코드가 파이선 2에서도 동작할것이라고 생각하지만 테스트를 해 보지는 않았다.



BusPirate가 제대로 동작하는지 확인하기 위해 BusPirate의 빌트인 테스트 루틴을 실행하는걸로 시작했다. 상세한 내용은 가이드를 참고하면 된다. 이 테스트는 아래 그림처럼 두 쌍의 핀을 서로 연결해 준 다음, BusPirate를 시리얼 터미널로 연결하고 '~' 명령을 실행하면 된다. 그러면 모든 유용한 정보를 출력해 준다.



다음은 모든 핀들을 동작시키기 위해 마이컴에서 실행될 코드이다. (main.c로 저장) 여기서는 MCU로 ATTiny85를 사용했다. 표준 클럭 설정(내장 RC클럭, 8MHz)을 사용하지만 외부 클럭소스나 크리스털을 사용하기 위해 퓨즈 설정을 바꾸길 원하면 engbedded's handy dandy fuse calculator를 사용해 계산한다.

#define F_CPU (8000000UL)
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRB = 255;
  while (1) {
    PORTB ^= 255;
    _delay_ms(500);
  }
}

코드 컴파일 및 MCU 프로그래밍을 위해 항상 같은 폴더에 bash 스크립트를 만들어 더블클릭하면 이전에 컴파일 된 파일들을 삭제하고, main.c를 컴파일 한 다음 BusPirate를 사용해 MCU에 프로그래밍 하게 해 놓았다. 스크립트에서 COM3는 자신의 컴퓨터에 BusPirate에 맞게 바꿔줘야 한다.

@echo off
del *.elf
del *.hex
avr-gcc -mmcu=attiny85 -Wall -Os -o main.elf main.c
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avrdude -c buspirate -p attiny85 -P com3 -e -U flash:w:main.hex
python up.py
 
비록 프로그래머가 +5V 핀을 통해 MCU에 전원을 공급해 주지만 프로그래밍이 끝나면 전원이 끊어진다.  수동으로 터미널 프로그램을 다시 열어 BusPirate에 재접속 하고 'm' 명령으로 모드를 리셋하고 '9' 명령으로 DIO 모드로 만든 다음 'W'명령으로 전원 출력을 재활성화 시키는 대신 이 모든것을 자동화 하길 원한다. 파이선을 사용하면 이 모든것을 쉽게 할 수 있다. 스크립트의 마지막 줄이 up.py를 호출한다. 이 팬시 스크립트는 전원을 켠 다음 심지어 Vcc라인의 전압까지도 출력 해 준다.  

""" python3 control of buspirate (SWHarden.com) """
import serial

BUSPIRATE_PORT = 'com3'

def send(ser.cmd):
  ser.write(str(cmd+'\n').encode('ascii'))
  for line in ser.readlines():
    print (line.decode('utf-8').strip())

ser = serial.Serial(BUSPIRATE_PORT, 115200, timeout=1)
assert ser.isOpen()
send(ser, '#')
send(ser, 'm')
send(ser, '9')
send(ser, 'W')
send(ser, 'v')
ser.close()
print ("disconnected!")

"burn.cmd"가 실행되면 코드가 컴파일되어 MCU에 프로그래밍 되고 전원공급을 켜고 Vcc의 전압을 알려준다. 출력은 다음과 같다.

C:\Users\scott\Documents\important\AVR\2016-07-13 ATTiny85 LEDblink>burn.cmd

Detecting BusPirate...
**
**  Bus Pirate v3a
**  Firmware v5.10 (r559)  Bootloader v4.4
**  DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  http://dangerousprototypes.com
**
BusPirate: using BINARY mode
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.12s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip
avrdude: reading input file "main.hex"
avrdude: input file main.hex auto detected as Intel Hex
avrdude: writing flash (84 bytes):

Writing | ################################################## | 100% 3.12s

avrdude: 84 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex auto detected as Intel Hex
avrdude: input file main.hex contains 84 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 2.72s

avrdude: verifying ...
avrdude: 84 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

#
RESET

Bus Pirate v3a
Firmware v5.10 (r559)  Bootloader v4.4
DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
http://dangerousprototypes.com
HiZ>
m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)

(1)>
9
Ready
DIO>
W
Power supplies ON
DIO>
v
Pinstates:
1.(BR)  2.(RD)  3.(OR)  4.(YW)  5.(GN)  6.(BL)  7.(PU)  8.(GR)  9.(WT)  0.(Blk)
GND     3.3V    5.0V    ADC     VPU     AUX     CLK     MOSI    CS      MISO
P       P       P       I       I       I       I       I       I       I
GND     3.17V   5.00V   0.00V   0.00V   L       L       L       H       L
DIO>
disconnected!

이는 최소한의 케이스 시나리오지만 더 복잡한 태스크를 수행하도록 확장할 수 있다. 예를 들어 모든 커맨드가 단일 파이선 프로그램에서 실행될 수 있다. BusPirate의 수 많은 다른 프로토콜과 통신할 수 있는 능력을 감안하면 별도의 특별한 추가 라이브러리를 설치하지 않고 파이선에서 네이티브하게 제어할 수 있다는건 매우 편리하다.

--
Credit goes to Scott W. Harden




2015년 4월 2일 목요일

BusPirate로 TinyRTC 사용해보기



BusPirate를 TinyRTC와 연결(3.3V, GND, SCL, SDA) 한 다음 시리얼 터미널을 열어준다. 통신 파라미터는 115200-N81이다.



HiZ>#
RESET

Bus Pirate v3b
Firmware v5.10 (r559) Bootloader v4.4
DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
http://dangerousprototypes.com
HiZ>?
General.....Protocol interaction
---------------------------------------------------------------------------
?.This help...(0).List current macros
=X/|X.Converts X/reverse X..(x).Macro x
~.Selftest...[.Start
#.Reset....].Stop
$.Jump to bootloader..{.Start with read
&/%.Delay 1 us/ms...}.Stop
a/A/@.AUXPIN (low/HI/READ).."abc".Send string
b.Set baudrate...123
c/C.AUX assignment (aux/CS)..0x123
d/D.Measure ADC (once/CONT.).0b110.Send value
f.Measure frequency..r.Read
g/S.Generate PWM/Servo../.CLK hi
h.Commandhistory...\.CLK lo
i.Versioninfo/statusinfo..^.CLK tick
l/L.Bitorder (msb/LSB)..-.DAT hi
m.Change mode..._.DAT lo
o.Set output type.....DAT read
p/P.Pullup resistors (off/ON).!.Bit read
s.Script engine...:.Repeat e.g. r:10
v.Show volts/states....Bits to read/write e.g. 0x55.2
w/W.PSU (off/ON)..<x>/<x= >/<0>.Usermacro x/assign x/list all
HiZ>m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)

(1)>4
Set speed:
1. ~5KHz
2. ~50KHz
3. ~100KHz
4. ~400KHz

(1)>4
Ready
I2C>(1)
Searching I2C address space. Found devices at:
Warning: *Short or no pull-up

I2C>W
Power supplies ON
I2C>(1)
Searching I2C address space. Found devices at:
0xA0(0x50 W) 0xA1(0x50 R) 0xD0(0x68 W) 0xD1(0x68 R)

I2C를 스캔한 결과 2개의 I2C주소를 사용하고 있는걸 확인할 수 있다. (0x50, 0x68)
하지만 주소 각각에 대해 R, W 주소가 다르게 나온건 I2C는 7비트 주소를 사용하고, 그 주소가 b7~b1까지에 들어가고 b0가 R/W를 나타내기 때문에 0x68인 경우 0b11010000(0xd0)이 0x68에 대한 write, 0b11010001(0xd1)이 0x68에 대한 read가 된다. Realtime Clock칩인 DS1307의 주소는 0x68이다.

DS1307의 레지스터 맵은 다음과 같다.



이제 TinyRTC에 시간을 설정해 보도록 하겠다. 2014년 4월 2일 (목) 오전 11:23:36으로 설정한다.
그러면 실제 레지스터에 넣어줘야 하는 값은 다음과 같다. (바탕이 회색인 부분은 설정에 사용되지 않으므로 무시, 바탕이 노란색인 부분의 볼드체 숫자는 바이너리 값이 아니고 BCD 값임)

AddressB7B6B5B4B3B2B1B0Hex ValueMeaning
0x0
0
3
6
0x3636 (sec), Clock enabled
0x1
0
2
3
0x2323 (min)
0x2
0
1
0
1
1
0x5111 (Hour), 12-hour mode, AM
0x3
0
0
0
0
0
4
0x044th day of the week
0x4
0
0
0
2
0x022 (date)
0x5
0
0
0
0
4
0x044 (month)
0x6
1
4
0x142014 (year)
0x7
0
0
0
0
0
0
0
0
0x00Square-wave disabled
0x8~0x3f









56 bytes RAM
즉 주소 0번지부터 0x36, 0x23, 0x51, 0x04, 0x02, 0x04, 0x14, 0x00을 넣어주면 되는 것이다.
BusPirate에서 다음 명령으로 값을 써 줄 수 있다. 데이터를 write하는 것이기 때문에 I2C 주소로 0xd0를 사용한다.

I2C>[0xd0 0x0 0x36 0x23 0x51 0x04 0x02 0x04 0x14 0x0]
I2C START BIT
WRITE: 0xD0 ACK
WRITE: 0x00 ACK
WRITE: 0x36 ACK
WRITE: 0x23 ACK
WRITE: 0x51 ACK
WRITE: 0x04 ACK
WRITE: 0x02 ACK
WRITE: 0x04 ACK
WRITE: 0x14 ACK
WRITE: 0x00 ACK
I2C STOP BIT

이제 원하는 시간이 설정이 되었고 클럭을 enabled 시켜줬기 때문에 시간이 계속 진행된다. 조금 후 현재 시간을 확인해 보도록 한다. 주소 0x0에서부터 7 바이트를 읽어보면 된다. 주소를 지정하기 위해 0x0을 쓸때는 I2C 주소로 0xd0를 사용하고, 데이터를 읽을때는 I2C 주소로 0xd1을 사용한걸 주의해라.

I2C>[0xd0 0x0]
I2C START BIT
WRITE: 0xD0 ACK
WRITE: 0x00 ACK
I2C STOP BIT
I2C>[0xd1 r r r r r r r]
I2C START BIT
WRITE: 0xD1 ACK
READ: 0x07
READ: ACK 0x25
READ: ACK 0x51
READ: ACK 0x04
READ: ACK 0x02
READ: ACK 0x04
READ: ACK 0x14
NACK
I2C STOP BIT

위의 결과를 분석해 보면 2014년 4월 2일 (목) 오전 11:25:07 이 된다. 설정된 시간에서 약 1분 30초 정도 지난걸 확인할 수 있다.

AddressB7B6B5B4B3B2B1B0Hex ValueMeaning
0x0
0
0
7
0x0707 (sec), Clock enabled
0x1
0
2
5
0x2525 (min)
0x2
0
1
0
1
1
0x5111 (Hour), 12-hour mode, AM
0x3
0
0
0
0
0
4
0x044th day of the week
0x4
0
0
0
2
0x022 (date)
0x5
0
0
0
0
4
0x044 (month)
0x6
1
4
0x142014 (year)
0x7
0
0
0
0
0
0
0
0
0x00Square-wave disabled
0x8~0x3f









56 bytes RAM

또한 위의 두 명령을 아래와 같이 한줄로 써 줄수도 있다.

I2C>[0xd0 0x0 [0xd1 r r r r r r r]
I2C START BIT
WRITE: 0xD0 ACK
WRITE: 0x00 ACK
I2C START BIT
WRITE: 0xD1 ACK
READ: 0x54
READ: ACK 0x30
READ: ACK 0x51
READ: ACK 0x04
READ: ACK 0x02
READ: ACK 0x04
READ: ACK 0x14
NACK
I2C STOP BIT
I2C>