Эта статья посвящена устройству выполняющему те же функции, что и устройство из прошлой статьи. Стоить отметить, описанное в этой статье устройство было сделано раньше. Изложение получается немного непоследовательным. Однако, надеюсь, статья будет не безынтересной.
Описываемое устройство состоит исключительно из ардуино нано. Экранчика нет. Данные передаются через UART. Но это не единственное отличие. Устройство производит измерение времени присутствия на линии и логической единицы и логического ноля. Здесь необходимо привести некоторые расчеты.
Логическая единица присутствует на линии от 1000 до 2000 микросекунд. Логический ноль присутствует на линии от 19 до 18 миллисекунд.
Я решил передавать данные с 38400 bps. Для передачи одного байта необходимо:
(1.0 / 38400.0) * 10.0 * 1000000.0 =260.417 мкс (us)
В байте восемь бит. Но рассчитано время необходимое для передачи 10 бит. Объяснение можно найти в описании UART. Перед передачей основных данных обязательно передается стартовый бит. Завершается передача минимум одним стоп битом (зависит от настроек).
Данные будут передаваться по три байта. Первый байт указывает логический уровень. l обозначает логический ноль. h обозначает логическую единицу. Следующие два байта содержат время присутствия логического уровня на линии. Вначале передается младший байт. Последним передается старший байт .
На передачу всех трех байт нужно:
260.417*3.0=781.251 мкс (us)
Результат вполне приемлем. С передачей данных проблем быть не должно.
Скажу несколько слов о выборе таймера/счетчика. В данном случае прекрасно подходит шестнадцатибитный таймер/счетчик. Он считает от 0 до 65535. При тактовой частоте микроконтроллера в 16 MHz и установленном на 8 предделителе таймера/счетчика, максимальный временной интервал, который может быть измерен, составляет:
(1.0 / (16000000.0 / 8.0)) * 65536.0 * 1000000.0 = 32768 мкс (us)
Этого более чем достаточно. При этом значение счетного регистра таймера/счетчика изменится на одну единицу за:
(1.0 / (16000000.0 / 8.0)) * 1.0 * 1000000.0 = 0.5 мкс (us)
Чтобы преобразовать в микросекунды число взятое из счетного регистра таймера/счетчика, его достаточно разделить на два. Это можно сделать сдвигом на 1 бит вправо.
Ниже приводится текст программы. Программа написана на ассемблере для микроконтроллера ATmega328 работающего на частоте 16 MHz. Скомпилировать её можно в Atmel Studio. Полученная прошивочка может быть загружена в любую ардуину с микроконтроллером ATmega328 работающем на частоте 16 MHz.
Приведу пример подключения приемника HobbyKing HK6DF к Arduino Nano.
Arduino Nano --- RC Receiver
A0 --- CH1
5V --- VCC
GND --- GND
Приемник получает питание от ардуино. Последняя питается от USB. Сигнал с приемника подается на нулевой аналоговый (четырнадцатый цифровой) вывод ардуино.
Для корректного отображения данных, передаваемых устройством на компьютер, необходима специальная программа. Я написал её на python. Код привожу ниже.
У меня программа работает через порт COM15. Этот номер Windows присвоила моей ардуино нано. Это единственный параметр который требует изменения для конкретной платки ардуино.
Результат работы программы выглядит так:
Описываемое устройство состоит исключительно из ардуино нано. Экранчика нет. Данные передаются через UART. Но это не единственное отличие. Устройство производит измерение времени присутствия на линии и логической единицы и логического ноля. Здесь необходимо привести некоторые расчеты.
Логическая единица присутствует на линии от 1000 до 2000 микросекунд. Логический ноль присутствует на линии от 19 до 18 миллисекунд.
Я решил передавать данные с 38400 bps. Для передачи одного байта необходимо:
(1.0 / 38400.0) * 10.0 * 1000000.0 =260.417 мкс (us)
В байте восемь бит. Но рассчитано время необходимое для передачи 10 бит. Объяснение можно найти в описании UART. Перед передачей основных данных обязательно передается стартовый бит. Завершается передача минимум одним стоп битом (зависит от настроек).
Данные будут передаваться по три байта. Первый байт указывает логический уровень. l обозначает логический ноль. h обозначает логическую единицу. Следующие два байта содержат время присутствия логического уровня на линии. Вначале передается младший байт. Последним передается старший байт .
На передачу всех трех байт нужно:
260.417*3.0=781.251 мкс (us)
Результат вполне приемлем. С передачей данных проблем быть не должно.
Скажу несколько слов о выборе таймера/счетчика. В данном случае прекрасно подходит шестнадцатибитный таймер/счетчик. Он считает от 0 до 65535. При тактовой частоте микроконтроллера в 16 MHz и установленном на 8 предделителе таймера/счетчика, максимальный временной интервал, который может быть измерен, составляет:
(1.0 / (16000000.0 / 8.0)) * 65536.0 * 1000000.0 = 32768 мкс (us)
Этого более чем достаточно. При этом значение счетного регистра таймера/счетчика изменится на одну единицу за:
(1.0 / (16000000.0 / 8.0)) * 1.0 * 1000000.0 = 0.5 мкс (us)
Чтобы преобразовать в микросекунды число взятое из счетного регистра таймера/счетчика, его достаточно разделить на два. Это можно сделать сдвигом на 1 бит вправо.
Ниже приводится текст программы. Программа написана на ассемблере для микроконтроллера ATmega328 работающего на частоте 16 MHz. Скомпилировать её можно в Atmel Studio. Полученная прошивочка может быть загружена в любую ардуину с микроконтроллером ATmega328 работающем на частоте 16 MHz.
;---------------------------------------------
; Program : Tester
; Compiler : AVR Studio
; Chip type : ATmega328P
; System Clock : 16 MHz
; Date :
;---------------------------------------------
.include "m328Pdef.inc"
;---------------------------------------------
; Interrupt vectors
.cseg
.org 0x0000 ; Reset
jmp RESET
.org 0x0002 ; External Interrupt Request 0
reti
.org 0x0004 ; External Interrupt Request 1
reti
.org 0x0006 ; Pin Change Interrupt Request 0
reti
.org 0x0008 ; Pin Change Interrupt Request 1
reti
.org 0x000A ; Pin Change Interrupt Request 2
reti
.org 0x000C ; Watchdog Time-out Interrupt
reti
.org 0x000E ; Timer/Counter 2 Compare Match A
reti
.org 0x0010 ; Timer/Counter 2 Compare Match B
reti
.org 0x0012 ; Timer/Counter 2 Overflow
reti
.org 0x0014 ; Timer/Counter 1 Capture Event
reti
.org 0x0016 ; Timer/Counter 1 Compare Match A
reti
.org 0x0018 ; Timer/Counter 1 Compare Match B
reti
.org 0x001A ; Timer/Counter 1 Overflow
reti
.org 0x001C ; Timer/Counter 0 Compare Match A
reti
.org 0x001E ; Timer/Counter 0 Compare Match B
reti
.org 0x0020 ; Timer/Counter 0 Overflow
reti
.org 0x0022 ; SPI Serial Transfer Complete
reti
.org 0x0024 ; USART, Rx Complete
reti
.org 0x0026 ; USART, UDR Empty
reti
.org 0x0028 ; USART, Tx Complete
reti
.org 0x002A ; ADC Conversion Complete
reti
.org 0x002C ; EEPROM Ready
reti
.org 0x002E ; Analog Comparator
reti
.org 0x0030 ; Two-wire Serial Interface
reti
.org 0x0032 ; Store Program Memory Read
reti
.org INT_VECTORS_SIZE
;---------------------------------------------
RESET:
;---------------------------------------------
; Steck initialization
ldi R16, Low(RAMEND)
out SPL, R16
ldi R16, High(RAMEND)
out SPH, R16
;---------------------------------------------
; Input/Output Ports
ldi R16, 0b00000000
out PORTB, R16
ldi R16, 0b00000000
out DDRB, R16
ldi R16, 0b00000000
out PORTC, R16
ldi R16, 0b00000000
out DDRC, R16
ldi R16, 0b00000000
out PORTD, R16
ldi R16, 0b00000000
out DDRD, R16
;---------------------------------------------
; USART
; Set baud rate (38400 bps)
ldi R16, 0
sts UBRR0H, R16
ldi R16, 51
sts UBRR0L, R16
; Enable double speed
ldi R16, (1<<U2X0)
sts UCSR0A, R16
; Enable transmitter
ldi R16, (1<<TXEN0)
sts UCSR0B, R16
; Set frame format: 8 data, 1 stop bit
ldi R16, (1<<UCSZ01)|(1<<UCSZ00)
sts UCSR0C, R16
;---------------------------------------------
; Timer/Counter 1
ldi R16, 0
sts TCNT1H, R16
sts TCNT1L, R16
ldi R16, 0
sts TCCR1A, R16
ldi R16, (1<<CS11)
sts TCCR1B, R16
ldi R16, 0
sts TCCR1C, R16
ldi R16, 0
sts TIMSK1, R16
ldi R16, 0
out TIFR1, R16
;---------------------------------------------
; Global interrupt disable
cli
;---------------------------------------------
; main
main:
ldi R16, 0
l_1:
sbis PINC, 0
rjmp l_1
lds R17, TCNT1L
lds R18, TCNT1H
sts TCNT1H, R16
sts TCNT1L, R16
; Divide R18:R17 by two
lsr R18
ror R17
ldi R19, 'l' ; Load 'l' to R19
rcall USART_Transmit
mov R19, R17 ; Copy R17 to R19
rcall USART_Transmit
mov R19, R18 ; Copy R18 to R19
rcall USART_Transmit
ldi R16, 0
l_2:
sbic PINC, 0
rjmp l_2
lds R17, TCNT1L
lds R18, TCNT1H
sts TCNT1H, R16
sts TCNT1L, R16
; Divide R18:R17 by two
lsr R18
ror R17
ldi R19, 'h' ; Load 'h' to R19
rcall USART_Transmit
mov R19, R17 ; Copy R17 to R19
rcall USART_Transmit
mov R19, R18 ; Copy R18 to R19
rcall USART_Transmit
rjmp main
;---------------------------------------------
; USART transmit
USART_Transmit:
; Wait for empty transmit buffer
lds R16, UCSR0A
sbrs R16, UDRE0
rjmp USART_Transmit
; Put data into buffer, sends the data
sts UDR0, R19
ret
;---------------------------------------------
Приведу пример подключения приемника HobbyKing HK6DF к Arduino Nano.
Arduino Nano --- RC Receiver
A0 --- CH1
5V --- VCC
GND --- GND
Приемник получает питание от ардуино. Последняя питается от USB. Сигнал с приемника подается на нулевой аналоговый (четырнадцатый цифровой) вывод ардуино.
Для корректного отображения данных, передаваемых устройством на компьютер, необходима специальная программа. Я написал её на python. Код привожу ниже.
#!/usr/bin/env python
# -*- coding: cp1251 -*-
import serial
# open port: COM15
# baud rate: 38400 bps
# frame format: 8 data, 1 stop bit
ser = serial.Serial(14,
38400,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1)
print ser, '\n' # print port information
while 1 :
temp = ser.read()
if temp != 'h' :
continue
temp = ser.read()
if temp :
vcc = ord(temp)
else :
continue
temp = ser.read()
if temp :
vcc |= (ord(temp)<<8)
else :
continue
temp = ser.read()
if temp != 'l' :
continue
temp = ser.read()
if temp :
gnd = ord(temp)
else :
continue
temp = ser.read()
if temp :
gnd |= (ord(temp)<<8)
else :
continue
print vcc, gnd, (vcc + gnd)
ser.close() # close port
У меня программа работает через порт COM15. Этот номер Windows присвоила моей ардуино нано. Это единственный параметр который требует изменения для конкретной платки ардуино.
Результат работы программы выглядит так:

Комментариев нет:
Отправить комментарий