370 likes | 383 Views
임베디드 프로그래밍. Lecture #04 2018. 10. 30. 목 차. 아날로그 입 출 력 테스트 I2C 통신 테스트 SPI 통신 테스트. 아날로그 입출력 (1). 아날로그 입력 대부분의 저항성 센서는 아날로그 신호로 측정값을 출력 저항성 센서의 기본 회로 : 저항병렬연결의 분압 원리 이용 센서값 처리를 위해서는 아날로그 신호의 디지털 값으로 변환 필요 ADC(Analog-to-Digital Converter). 고정 저항. 저항성 센서. Vcc. GND. 센서값 측정.
E N D
임베디드 프로그래밍 Lecture #04 2018. 10. 30
목 차 • 아날로그 입출력 테스트 • I2C 통신 테스트 • SPI 통신 테스트
아날로그 입출력 (1) • 아날로그 입력 • 대부분의 저항성 센서는 아날로그 신호로 측정값을 출력 • 저항성 센서의 기본 회로: 저항병렬연결의 분압 원리 이용 • 센서값 처리를 위해서는 아날로그 신호의 디지털 값으로 변환 필요 • ADC(Analog-to-Digital Converter) 고정 저항 저항성 센서 Vcc GND 센서값 측정
아날로그 입출력 (2) • 아날로그 출력 • 대부분의 액츄에이터(Actuator) 장치는 아날로그 신호로 제어 • 예: • 서보 모터/ DC 모터 속도 제어 • LED 밝기 제어 등 • 디지털 값을 아날로그 신호로 변환하는 장치가 필요 • Hardware PWM • Software PWM • DAC(Digital-to-Analog Converter)
아날로그 입출력 (3) • 라즈베리파이의 아날로그 입출력 (1) • 라즈베리파이는ADC/DAC 장치를 지원하지 않는다 라즈베리파이만으로는 아날로그 입출력을 수행하지 못함. • 별도의 ADC/DAC 장치를 이용하여 아날로그 입출력 처리 • MCP4911, MCP3002, PCF8591 등 • 외부 ACD/DAC와 라즈베리파이 사이의 인터페이스(통신방식) • I2C(Inter-IC) • SPI(Serial Peripheral Interface)
아날로그 입출력 (4) • 라즈베리파이의 아날로그 입출력 (2) ADC Sensors RaspberryPi I2C / SPI Actuator DAC
아날로그 입출력 (5) • I2C(Inter-IC) 시리얼 통신 • 단방향 동기식 직렬 통신
아날로그 입출력 (6) • SPI(Serial Peripheral Interface) 시리얼 통신 • 양방향 동기식 직렬 통신
아날로그 입출력 (7) • PCF8591 Breakout Board • PCF8591T : 8-bit AD-DA Converter / I2C Interface
아날로그 입출력 (8) • PCF8591 Breakout Board • PCF8591T Spec: • Addressing: • Control byte: A2: High, A1: Low A0: Low => 주소: 0x48
아날로그 입출력 (9) • PCF8591 Breakout Board • Jumper Setting • AIN0 <-->INPUT0(Potentiometer) • AIN1 <-->INPUT1(Photoresistor) • AIN2 <-->INPUT2(Themistor) • AIN3 • AOUT
아날로그 입출력 (10) • PCF8591 Breakout Board 연결 • 라즈베리파이와의 연결 • DAC 테스트 연결 Pin 3 Pin 5 Pin 1 Pin 9 실습키트LED S1 AOUT GND
아날로그 입출력(11) • 라즈베리파이의I2C Bus 설정 (1) • 라즈베리파이 설정 유틸리티 “raspi-config”을 이용하여 I2C 장치를 사용 가능하도록 설정 # sudoraspi-config • I2C Tool 설치 # sudo apt-get install i2c-tools • I2C 사용자 그룹에 “pi” user 추가 # sudoadduser pi i2c
아날로그 입출력(12) • 라즈베리파이의I2C Bus 설정(2) • I2C Tool 테스트 및 i2c slave 장치 주소 확인 # sudo i2cdetect –l // i2c 장치 목록 확인 # sudo i2cdetect –y 1 PCF8591 Breakout board의 주소는 0x48
아날로그 입출력(13) • I2C Bus 입출력 테스트 (1) • PCF8591 AIN0 값 읽기 # sudoi2cset –y 1 0x48 0x00 // send control byte to read AIN0(Potentiometer) # sudo i2cget –y 1 0x48 // read one byte from bus 1 dev 0x48 # sudo i2cget –y 1 0x48 # sudo i2cget –y 1 0x48 샘플링 지연으로 인해 첫 번째 읽은 값과 두 번째 읽은 값이 다를 수 있음
아날로그 입출력(14) • I2C Bus 입출력 테스트 (2) • PCF8591 AIN1 값 읽기 # sudoi2cset –y 1 0x48 0x01 // set control byte to read AIN1(Photoresistor) # sudo i2cget –y 1 0x48 // read one byte from bus 1 dev 0x48 # sudo i2cget –y 1 0x48 # sudo i2cget –y 1 0x48
아날로그 입출력(15) • I2C Bus 입출력 테스트 (3) • PCF8591 AOUT(PWM) 출력 # sudo i2cset –y 1 0x48 0x40 0xff // set a value 0xff to AOUT # sudo i2cset –y 1 0x48 0x40 0xc0// set a value 0xc0 to AOUT # sudo i2cset –y 1 0x48 0x40 0x90// set a value 0x90 to AOUT # sudo i2cset –y 1 0x48 0x40 0x00// set a value 0x00 to AOUT PCF8591 Breakout 보드 위의 LED 밝기 변화를 확인
아날로그 입출력 (16) • PCF8591 Breakout Board 테스트 (1) • NetBeans IDE를 이용한 테스트 프로그램 작성 및 테스트 • 아날로그 입력값을 읽어 화면에 출력 • 아날로그 출력을 이용하여 LED Dimming • NetBeans IDE에서 새로운 프로젝트 생성 • 프로젝트명: jiot04_PCF8591BB_test • Main Class Name: jiot04.pcf8591bb_test.PCF8591BBTest • 프로젝트 속성 설정에서 라이브러리 추가 • dio.jar 라이브러리 추가
아날로그 입출력 (17) • PCF8591 Breakout Board 테스트 (2) • jdk.dio.i2cdev 패키지를 이용하여 I2C 장치 드라이브 구현 • “source packages” 내에 “i2c_dev” 패키지 생성 • “i2c_dev” 패키지 내에 다음의 클래스 파일 생성 • I2CRPi.java – I2C Device wrapper class • I2CUtils.java – I2C Device I/O utility method(static method) 지원 • PCF8591.java – PCF8591 IC의 register I/O enumerator 객체 정의
아날로그 입출력 (18) • PCF8591 Breakout Board 테스트 (3) • i2c_dev.I2CRPi.java package i2c_dev; import java.io.IOException; import jdk.dio.DeviceManager; import jdk.dio.i2cbus.I2CDevice; import jdk.dio.i2cbus.I2CDeviceConfig; public class I2CRPi { private I2CDeviceConfig config; public I2CDevice device = null; public I2CRPi(int i2cAddress) throws IOException { config = new I2CDeviceConfig.Builder() .setAddress(i2cAddress, I2CDeviceConfig.ADDR_SIZE_7) .build(); device = (I2CDevice) DeviceManager.open(I2CDevice.class, config); } public void close() { try { device.close(); } catch (IOException ex) { ex.printStackTrace(); } } }
아날로그 입출력 (19) • PCF8591 Breakout Board 테스트 (4) • i2c_dev.I2CUtils.java package i2c_dev; import java.io.IOException; import java.nio.ByteBuffer; import jdk.dio.i2cbus.I2CDevice; /** * Functions to read and write to I2C Raspberry Pi bus * */ public class I2CUtils { /** * * @parammili */ public static void I2Cdelay(intmili) { try { Thread.sleep(mili); } catch (InterruptedException ex) { } } /** * @parammili * @paramnano */ public static void I2CdelayNano(intmili, intnano) { try { Thread.sleep(mili, nano); } catch (InterruptedException ex) { } } /** * @param b * @return byte values from -127..128 convert 128..255 */ public static intasInt(byte b) { inti = b; if (i < 0) { i += 256; } return i; }
/** * @param device Device connected to I2C bus * @paramcmd Command send to device * @return read an int from a device connected to I2C bus */ public static int read(I2CDevice device, intcmd) { ByteBufferrxBuf = ByteBuffer.allocateDirect(1); try { device.read(cmd, 1, rxBuf); } catch (IOException ex) { //Logger.getGlobal().log(Level.WARNING,ex.getMessage()); //ex.printStackTrace(); System.out.println("WARNING: " + ex.getMessage()); } return asInt(rxBuf.get(0)); } /** * @param device Device connected to I2C bus * @paramcmd Command send to Arduino Due * @return read a float from Arduino Due connected to I2C bus. All bytes * received must be swamp order */ public static float readFloatArduino(I2CDevice device, intcmd) { byte[] b = new byte[4]; ByteBufferrxBuf = ByteBuffer.allocateDirect(4); try { device.read(cmd, 4, rxBuf); } catch (IOException ex) { //Logger.getGlobal().log(Level.WARNING, ex.getMessage()); System.out.println("WARNING: " + ex.getMessage()); } rxBuf.clear(); for (inti = 0; i < 4; i++) { b[i] = rxBuf.get(3 - i); } return ByteBuffer.wrap(b).getFloat(); } /** * @param device Device connected to I2C bus * @paramcmd Command send to Arduino Due * @return read a short from Arduino Due connected to I2C bus. All bytes * received must be swamp order */ public static short readShortArduino(I2CDevice device, intcmd) { byte[] b = new byte[2]; ByteBufferrxBuf = ByteBuffer.allocateDirect(2); try { device.read(cmd, 2, rxBuf); } catch (IOException ex) { //Logger.getGlobal().log(Level.WARNING, ex.getMessage()); System.out.println("WARNING: " + ex.getMessage()); } rxBuf.clear(); for (inti = 0; i < 2; i++) { b[i] = rxBuf.get(1 - i); } return ByteBuffer.wrap(b).getShort(); } /** * @param device Device connected to I2C bus * @paramcmd Command send to a device * @return read a short from a device connected to I2C bus */ public static short readShort(I2CDevice device, intcmd) { //byte[] b = new byte[2]; ByteBufferrxBuf = ByteBuffer.allocateDirect(2);
try { device.read(cmd, 1, rxBuf); } catch (IOException ex) { //Logger.getGlobal().log(Level.WARNING, ex.getMessage()); System.out.println("WARNING: " + ex.getMessage()); } rxBuf.clear(); return rxBuf.getShort(); } /** * @param device Device connected to I2C bus * @paramcmd Command send to a device * @param value Command value to wite to device */ public static void write(I2CDevice device, byte cmd, byte value) { ByteBuffertxBuf = ByteBuffer.allocateDirect(2); txBuf.put(0, cmd); txBuf.put(1, value); try { device.write(txBuf); } catch (IOException ex) { //Logger.getGlobal().log(Level.WARNING, ex.getMessage()); System.out.println("WARNING: " + ex.getMessage()); } } /** * Write multiple bits in an 8-bit device register. * @paramdevAddr I2C slave device address * @paramregAddr Register regAddr to write to * @parambitStart First bit position to write (0-7) * @param length Number of bits to write (not more than 8) * @param data Right-aligned value to write */ public static void writeBits(I2CDevice devAddr, byte regAddr, intbitStart, int length, int data) { // 010 value to write // 76543210 bit numbers // xxx args: bitStart=4, length=3 // 00011100 mask byte // 10101111 original value (sample) // 10100011 original & ~mask // 10101011 masked | value byte b = (byte) read(devAddr, regAddr); if (b != 0) { int mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data b &= ~(mask); // zero all important bits in existing byte b |= data; // combine data with existing byte write(devAddr, regAddr, b); } } /** * write a single bit in an 8-bit device register. * * @paramdevAddr I2C slave device address * @paramregAddr Register regAddr to write to * @parambitNum Bit position to write (0-7) * @param data */ public static void writeBit(I2CDevice devAddr, byte regAddr, intbitNum, int data) { int b= (byte) read(devAddr, regAddr); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); write(devAddr, regAddr, (byte) b); } }
아날로그 입출력 (20) • PCF8591 Breakout Board 테스트 (5) • i2c_dev.PCF8591.java package i2c_dev; import jdk.dio.i2cbus.I2CDevice; public enum PCF8591 { /** * Analog Input 0 */ AIN0(0x0), /** * Analog Input 1 */ AIN1(0x01), /** * Analog Input 2 */ AIN2(0x02), /** * Analog Input 3 */ AIN3(0x03), /** * Analog Output */ AOUT(0x40); /** * */ public byte cmd; private PCF8591(intcmd) { this.cmd = (byte) cmd; } /** * @param device * @return */ public int read(I2CDevice device) { return I2CUtils.read(device, this.cmd); } /** * @param device * @param value */ public void write(I2CDevice device, int value) { I2CUtils.write(device, this.cmd, (byte)value); } }
아날로그 입출력 (21) • PCF8591 Breakout Board 테스트 (6) • 앞에서 구현한 I2C 장치 인터페이스 클래스를 이용하여 PCF8591 장치 드라이브 구현 • “source packages” 내에 “i2c_dev.drivers” 패키지 생성 • “i2c_dev.drivers” 패키지 내에 다음의 클래스 파일 생성 • PCF8591Device.java – PCF8591 IC의 장치 드라이브 클래스
아날로그 입출력 (22) • PCF8591 Breakout Board 테스트 (7) • i2c_dev.drivers.PCF8591Device.java switch (ainPin) { case 0: value = PCF8591.AIN0.read(device); break; case 1: value = PCF8591.AIN1.read(device); break; case 2: value = PCF8591.AIN2.read(device); break; case 3: value = PCF8591.AIN3.read(device); break; } return value; } public void analogWrite(intpwm) throws IOException { PCF8591.AOUT.write(device, pwm); } } package i2c_dev.drivers; import i2c_dev.I2CRPi; import i2c_dev.PCF8591; import java.io.IOException; public class PCF8591Device extends I2CRPi { private static final int PCF8591Addr = 0x48; public PCF8591Device() throws IOException { super(PCF8591Addr); device.write(0x00); } public intanalogRead(intainPin) { int value = 0;
아날로그 입출력 (23) • PCF8591 Breakout Board 테스트 (8) • PCF8591 장치 테스트 프로그램 구현 • Pcf8591bb_test.PCF8591Test.java • 아날로그 입력 0~3을순서대로 읽어 화면에 출력 • 아날로그 출력을 이용하여 LEDdimming
System.out.println("LED dimming..."); adConverter.analogWrite(0xff); I2CUtils.I2Cdelay(3000); adConverter.analogWrite(0xcf); I2CUtils.I2Cdelay(3000); adConverter.analogWrite(0xaf); I2CUtils.I2Cdelay(3000); adConverter.analogWrite(0x9f); I2CUtils.I2Cdelay(3000); adConverter.analogWrite(0x00); } catch (IOException ex) { System.out.println("ERROR: " + ex.getMessage()); } } // main() } package pcf8591bb_test; import i2c_dev.I2CUtils; import i2c_dev.drivers.PCF8591Device; import java.io.IOException; public class I2CTest { public static void main(String[] args) { try { PCF8591Device adConverter = new PCF8591Device(); adConverter.analogRead(0); I2CUtils.I2Cdelay(1000); adConverter.analogRead(0); I2CUtils.I2Cdelay(1000); System.out.println("Potentimeter Input : " + adConverter.analogRead(0)); I2CUtils.I2Cdelay(1000); adConverter.analogRead(1); I2CUtils.I2Cdelay(1000); System.out.println("Photoregister Input : " + adConverter.analogRead(1)); I2CUtils.I2Cdelay(1000); adConverter.analogRead(2); I2CUtils.I2Cdelay(1000); System.out.println("Themistor Input : " + adConverter.analogRead(2)); I2CUtils.I2Cdelay(1000);
아날로그 입출력 (24) • PCF8591 Breakout Board 테스트 (9) • 설정 파일 추가 • “lib” 디렉토리 추가 • 장치 레지스트리 파일 및 보안 정책 파일 추가 • build.xml 파일 수정
아날로그 입출력 (25) • PCF8591 Breakout Board 테스트 (10) • 설정 파일 – 장치 레지스트리 파일 • 본 예제에서는 프로그램 내에서 장치 설정을 동적으로 수행하기 때문에 장치 레지스트리 파일 내용이 영향을 미치지 않는다. # RPi3 header pins 1 = deviceType: gpio.GPIOPin, pinNumber:4, name:GPIO4, predefined:true 2 = deviceType: gpio.GPIOPin, pinNumber:7, name:GPIO7, mode:4, direction:1, predefined:true #3 = deviceType: gpio.GPIOPin, pinNumber:17, name:GPIO17, predefined:true 17 = deviceType: gpio.GPIOPin, pinNumber:17, name:GPIO17, mode:4, direction:1, predefined:true 4 = deviceType: gpio.GPIOPin, pinNumber:18, name:GPIO18, mode:4, direction:1, predefined:true 5 = deviceType: gpio.GPIOPin, pinNumber:22, name:GPIO22, predefined:true 6 = deviceType: gpio.GPIOPin, pinNumber:23, name:GPIO23, mode:2, direction:0, predefined:true 7 = deviceType: gpio.GPIOPin, pinNumber:24, name:GPIO24, mode:2, direction:0, predefined:true …
아날로그 입출력 (26) • PCF8591 Breakout Board 테스트 (11) • 설정 파일 – 보안 정책 파일 // policy for DIO framework grant { // Very permissive permissions permission jdk.dio.DeviceMgmtPermission "*:*", "open"; permission jdk.dio.gpio.GPIOPinPermission "*:*"; permission jdk.dio.i2cbus.I2CPermission "*:*"; permission jdk.dio.spibus.SPIPermission "*:*"; };
아날로그 입출력 (27) • PCF8591 Breakout Board 테스트 (12) • build.xml 파일 수정 lib
아날로그 입출력 (28) • PCF8591 Breakout Board 테스트 (13) • 프로젝트 속성 설정 수정 • Sources / Run 속성 수정
아날로그 입출력 (29) • PCF8591 Breakout Board 테스트 (14) • 원격 실행 • 원격 디버깅