Наработки за 5 лет
This commit is contained in:
commit
f5582d88c3
BIN
.csync_journal.db
Normal file
BIN
.csync_journal.db
Normal file
Binary file not shown.
BIN
.csync_journal.db-shm
Normal file
BIN
.csync_journal.db-shm
Normal file
Binary file not shown.
0
.csync_journal.db-wal
Normal file
0
.csync_journal.db-wal
Normal file
1650
.owncloudsync.log
Normal file
1650
.owncloudsync.log
Normal file
File diff suppressed because it is too large
Load Diff
366
HXbot/HX.py
Executable file
366
HXbot/HX.py
Executable file
@ -0,0 +1,366 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot utility module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
# I2C bus
|
||||
I2C_BUS_NUMBER = 2
|
||||
EXT_COM = 0xAA
|
||||
XOR_SEQ = 0xFF
|
||||
|
||||
# VAR
|
||||
REFLEX_ADDRESS = 0x04
|
||||
REFLEX_RESPONSE_DELAY = 0.1 # Delay to get response after send command, sec
|
||||
REFLEX_ERROR_LIMIT = 5
|
||||
REFLEX_MOVE_TIMEOUT = 60
|
||||
|
||||
# COMMANDS
|
||||
# Util
|
||||
COM_PING = 0x01
|
||||
COM_GET_TEMP = 0x02
|
||||
COM_GET_DISTANCE = 0x03
|
||||
|
||||
# Stop
|
||||
STOP = 0x0F
|
||||
# Move
|
||||
MOVE_FLAG = 0x04
|
||||
MOVE_FLOAT = 0x10
|
||||
MOVE_FWD1 = 0x11
|
||||
MOVE_FWD2 = 0x12
|
||||
MOVE_FWD3 = 0x13
|
||||
MOVE_FWD4 = 0x14
|
||||
MOVE_FWD5 = 0x15
|
||||
MOVE_FWD6 = 0x16
|
||||
MOVE_FWD7 = 0x17
|
||||
MOVE_BREAK = 0x18
|
||||
MOVE_REV7 = 0x19
|
||||
MOVE_REV6 = 0x1A
|
||||
MOVE_REV5 = 0x1B
|
||||
MOVE_REV4 = 0x1C
|
||||
MOVE_REV3 = 0x1D
|
||||
MOVE_REV2 = 0x1E
|
||||
MOVE_REV1 = 0x1F
|
||||
|
||||
# Steering
|
||||
STEER_FLAG = 0x05
|
||||
STEER_CENTER = 0x20
|
||||
STEER_LEFT1 = 0x21
|
||||
STEER_LEFT2 = 0x22
|
||||
STEER_LEFT3 = 0x23
|
||||
STEER_LEFT4 = 0x24
|
||||
STEER_LEFT5 = 0x25
|
||||
STEER_LEFT6 = 0x26
|
||||
STEER_LEFT7 = 0x27
|
||||
STEER_FIX_CENTER = 0x28
|
||||
STEER_RIGHT7 = 0x29
|
||||
STEER_RIGHT6 = 0x2A
|
||||
STEER_RIGHT5 = 0x2B
|
||||
STEER_RIGHT4 = 0x2C
|
||||
STEER_RIGHT3 = 0x2D
|
||||
STEER_RIGHT2 = 0x2E
|
||||
STEER_RIGHT1 = 0x2F
|
||||
|
||||
# Head
|
||||
HEAD_H_FLAG = 0x30
|
||||
HEAD_V_FLAG = 0x31
|
||||
HEAD_H_R_RANGE = 83
|
||||
HEAD_H_L_RANGE = 94
|
||||
HEAD_V_UP_RANGE = 90
|
||||
HEAD_V_DOWN_RANGE = 25
|
||||
HEAD_H_CENTER = 83
|
||||
HEAD_V_CENTER = 150
|
||||
|
||||
# CONTROL SOURCE
|
||||
CONTROL_SRC_NONE = 0x00
|
||||
CONTROL_SRC_JOYSTICK = 0x01
|
||||
CONTROL_SRC_IRREMOTE = 0x02
|
||||
CONTROL_SRC_SERVER = 0x03
|
||||
CONTROL_SRC_DB = 0x04
|
||||
CONTROL_SRC_SUB1 = 0x11
|
||||
CONTROL_SRC_SUB2 = 0x12
|
||||
CONTROL_SRC_SUB3 = 0x13
|
||||
CONTROL_SRC_SUB4 = 0x14
|
||||
CONTROL_SRC_SUB5 = 0x15
|
||||
|
||||
CONTROL_SRC_DEFAULT = CONTROL_SRC_JOYSTICK
|
||||
|
||||
# MOVE STATES
|
||||
MOVE_STATE_STOP = 0x00
|
||||
MOVE_STATE_MOVE = 0x01
|
||||
|
||||
# STATUS
|
||||
STATUS_INIT = 0x00
|
||||
STATUS_READY = 0x01
|
||||
STATUS_RUNNING = 0x02
|
||||
STATUS_STOP = 0x03
|
||||
STATUS_EXIT = 0x04
|
||||
|
||||
# STATUS STATES
|
||||
#STATUS_STATE_OK = 0x00
|
||||
#STATUS_STATE_WARNING = 0x01
|
||||
#STATUS_STATE_ERROR = 0x02
|
||||
#STATUS_STATE_LOWBAT1 = 0x03
|
||||
#STATUS_STATE_LOWBAT2 = 0x04
|
||||
|
||||
# JOYSTICK
|
||||
JOYSTICK_PATH = '/dev/input/js0'
|
||||
JOYSTICK_READY_TIMEOUT = 60
|
||||
|
||||
# These constants were borrowed from linux/input.h
|
||||
JOYSTICK_AXIS_NAMES = {
|
||||
0x00: 'x',
|
||||
0x01: 'y',
|
||||
0x02: 'z',
|
||||
0x03: 'rx',
|
||||
0x04: 'ry',
|
||||
0x05: 'rz',
|
||||
0x06: 'trottle',
|
||||
0x07: 'rudder',
|
||||
0x08: 'wheel',
|
||||
0x09: 'gas',
|
||||
0x0a: 'brake',
|
||||
0x10: 'hat0x',
|
||||
0x11: 'hat0y',
|
||||
0x12: 'hat1x',
|
||||
0x13: 'hat1y',
|
||||
0x14: 'hat2x',
|
||||
0x15: 'hat2y',
|
||||
0x16: 'hat3x',
|
||||
0x17: 'hat3y',
|
||||
0x18: 'pressure',
|
||||
0x19: 'distance',
|
||||
0x1a: 'tilt_x',
|
||||
0x1b: 'tilt_y',
|
||||
0x1c: 'tool_width',
|
||||
0x20: 'volume',
|
||||
0x28: 'misc',
|
||||
}
|
||||
|
||||
JOYSTICK_BUTTON_NAMES = {
|
||||
0x120: 'trigger',
|
||||
0x121: 'thumb',
|
||||
0x122: 'thumb2',
|
||||
0x123: 'top',
|
||||
0x124: 'top2',
|
||||
0x125: 'pinkie',
|
||||
0x126: 'base',
|
||||
0x127: 'base2',
|
||||
0x128: 'base3',
|
||||
0x129: 'base4',
|
||||
0x12a: 'base5',
|
||||
0x12b: 'base6',
|
||||
0x12f: 'dead',
|
||||
0x130: 'a',
|
||||
0x131: 'b',
|
||||
0x132: 'c',
|
||||
0x133: 'x',
|
||||
0x134: 'y',
|
||||
0x135: 'z',
|
||||
0x136: 'tl',
|
||||
0x137: 'tr',
|
||||
0x138: 'tl2',
|
||||
0x139: 'tr2',
|
||||
0x13a: 'select',
|
||||
0x13b: 'start',
|
||||
0x13c: 'mode',
|
||||
0x13d: 'thumbl',
|
||||
0x13e: 'thumbr',
|
||||
|
||||
0x220: 'dpad_up',
|
||||
0x221: 'dpad_down',
|
||||
0x222: 'dpad_left',
|
||||
0x223: 'dpad_right',
|
||||
|
||||
# XBox 360 controller uses these codes.
|
||||
0x2c0: 'dpad_left',
|
||||
0x2c1: 'dpad_right',
|
||||
0x2c2: 'dpad_up',
|
||||
0x2c3: 'dpad_down',
|
||||
}
|
||||
|
||||
# JOYSTICK BINDS
|
||||
JOYSTICK_MOVE_AXIS = 'y'
|
||||
JOYSTICK_STEER_AXIS = 'x'
|
||||
JOYSTICK_HEAD_V_AXIS = 'rz'
|
||||
JOYSTICK_HEAD_H_AXIS = 'z'
|
||||
JOYSTICK_START_BTN_1 = 'tl2'
|
||||
JOYSTICK_START_BTN_2 = 'tr2'
|
||||
|
||||
# HXpower
|
||||
POWER_ADDRESS = 0x05
|
||||
POWER_RESPONSE_DELAY = 0.05 # Delay to get response after send command, sec
|
||||
POWER_DELAY = 0.3
|
||||
POWER_ERROR_LIMIT = 3
|
||||
POWER_MV_TIMEOUT = 60
|
||||
|
||||
# Commands
|
||||
# VOLTMETERS
|
||||
COM_GET_VIN = 0x01
|
||||
COM_GET_VDC = 0x02
|
||||
COM_GET_VBT = 0x03
|
||||
COM_GET_VBA = 0x04
|
||||
COM_GET_VPF = 0x05
|
||||
COM_GET_VZU = 0x06
|
||||
COM_GET_VCC = 0x07
|
||||
|
||||
# AMPERMETERS
|
||||
COM_GET_ABT = 0x21
|
||||
COM_GET_ABA = 0x22
|
||||
COM_GET_AIN = 0x23
|
||||
COM_GET_AHX = 0x24
|
||||
|
||||
# STATUS
|
||||
COM_GET_STAT1 = 0x08
|
||||
# 0x01 - vcc_ok
|
||||
# 0x02 - vin_ok
|
||||
# 0x04 - vdc_ok
|
||||
# 0x08 - vbt_ok
|
||||
# 0x10 - vba_ok
|
||||
# 0x20 - bt_enabled
|
||||
# 0x40 - ba_enabled
|
||||
# 0x80 - in_plugged
|
||||
|
||||
COM_GET_STAT2 = 0x09
|
||||
# 0x01 - bt_blocked
|
||||
# 0x02 - ba_blocked
|
||||
# 0x04 - bt_full
|
||||
# 0x08 - ba_full
|
||||
# 0x10 - vpf_ok
|
||||
# 0x20 - vzu_ok
|
||||
# 0x40 - mv_enabled
|
||||
# 0x80 - us_enabled
|
||||
|
||||
COM_GET_STAT3 = 0x20
|
||||
# 0x01 - abt_ok
|
||||
# 0x02 - aba_ok
|
||||
# 0x04 - ain_ok
|
||||
# 0x08 - ahx_ok
|
||||
|
||||
# TEMP
|
||||
COM_GET_POWER_TEMP = 0x10
|
||||
|
||||
VIN_MIN = 10.0
|
||||
VIN_MAX = 14.0
|
||||
VIN_LOW = 11.0
|
||||
VIN_HIGH = 13.0
|
||||
|
||||
VDC_MIN = 5.0
|
||||
VDC_MAX = 5.7
|
||||
VDC_LOW = 5.1
|
||||
VDC_HIGH = 5.5
|
||||
|
||||
VBT_MIN = 3.65
|
||||
VBT_MAX = 4.25
|
||||
VBT_LOW = 3.68
|
||||
VBT_FULL = 4.1
|
||||
|
||||
VBA_MIN = 9.0
|
||||
VBA_MAX = 12.8
|
||||
VBA_LOW = 10.0
|
||||
VBA_FULL = 12.4
|
||||
|
||||
VPF_MIN = 7.2
|
||||
VPF_MAX = 10.0
|
||||
VPF_LOW = 8.0
|
||||
VPF_HIGH = 9.6
|
||||
|
||||
VZU_MIN = 5.0
|
||||
VZU_MAX = 6.3
|
||||
VZU_LOW = 5.2
|
||||
VZU_HIGH = 6.2
|
||||
|
||||
VCC_MIN = 4.5
|
||||
VCC_MAX = 5.3
|
||||
VCC_LOW = 4.7
|
||||
VCC_HIGH = 5.1
|
||||
|
||||
ABT_MIN = 0.3
|
||||
ABT_MAX = 2.0
|
||||
ABT_LOW = 0.4
|
||||
ABT_HIGH = 1.2
|
||||
|
||||
ABA_MIN = 0.05
|
||||
ABA_MAX = 2.0
|
||||
ABA_LOW = 0.5
|
||||
ABA_HIGH = 1.5
|
||||
|
||||
AIN_MIN = 0.05
|
||||
AIN_MAX = 2.0
|
||||
AIN_LOW = 0.1
|
||||
AIN_HIGH = 1.5
|
||||
|
||||
AHX_MIN = 0.05
|
||||
AHX_MAX = 3.0
|
||||
AHX_LOW = 0.1
|
||||
AHX_HIGH = 1.5
|
||||
|
||||
# RELAYS
|
||||
COM_ENABLE_BA = 0x11 # 17
|
||||
COM_ENABLE_MV = 0x12 # 18
|
||||
COM_ENABLE_BT = 0x13 # 19
|
||||
COM_ENABLE_US = 0x14 # 20
|
||||
|
||||
COM_DISABLE_BA = 0x15 # 21
|
||||
COM_DISABLE_MV = 0x16 # 22
|
||||
COM_DISABLE_BT = 0x17 # 23
|
||||
COM_DISABLE_US = 0x18 # 24
|
||||
|
||||
COM_RUN = 0x1B # 27
|
||||
COM_STOP = 0x1C # 28
|
||||
COM_RESET_US = 0x1D # 29
|
||||
|
||||
# HXserver
|
||||
SRV_PORT = 50306
|
||||
SRV_HOST = ''
|
||||
SRV_CMD_GET_ALL = 0x01
|
||||
SRV_TIMEOUT = 1
|
||||
SRV_MAX_ERR_COUNT = 3
|
||||
|
||||
# RETURN CODES
|
||||
# Universal return codes
|
||||
OK_RSP = 0x00
|
||||
NO_RSP = 0xFF
|
||||
ERR_RSP = 0x01
|
||||
BLK_RSP = 0x02
|
||||
CSE_RSP = 0x03
|
||||
IOE_RSP = 0x04
|
||||
TMO_RSP = 0x05
|
||||
|
||||
# HXbot modul flags
|
||||
I2C_BUS_ERR = 0x0001
|
||||
HXPOWER_ERR = 0x0002
|
||||
REFLEX_ERR = 0x0004
|
||||
SERVER_ERR = 0x0008
|
||||
|
||||
JOYSTICK_WRN = 0x0010
|
||||
HXCAMERA_WRN = 0x0020
|
||||
HXLCD_WRN = 0x0040
|
||||
HXDB_WRN = 0x0080
|
||||
HXLIGHT_WRN = 0x0100
|
||||
HXSOUND_WRN = 0x0200
|
||||
HXLOG_WRN = 0x0400
|
||||
|
||||
# HXlcd
|
||||
LCD_ADDRESS = 0x06
|
||||
LCD_ERROR_LIMIT = 5
|
||||
LCD_DELAY = 1
|
||||
LCD_RESPONSE_DELAY = 0.05
|
||||
|
||||
# HXcam
|
||||
CAM_MAX_WRN_COUNT = 3
|
||||
CAM_DELAY = 1.0
|
||||
|
||||
CAM_STATE_STP = 0
|
||||
CAM_STATE_RUN = 1
|
||||
CAM_STATE_WRN = 2
|
||||
CAM_STATE_ERR = 3
|
||||
|
||||
# HXdb
|
||||
DB_DELAY = 10.0
|
||||
|
||||
DB_HOST = 'localhost'
|
||||
DB_NAME = 'hxdb'
|
||||
DB_USER = 'hxdb'
|
||||
DB_PASS = 'hxdbP@S$'
|
711
HXbot/HXbot.py
Executable file
711
HXbot/HXbot.py
Executable file
@ -0,0 +1,711 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot main program #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import REflex
|
||||
import HXjoystick
|
||||
import HXpower
|
||||
import HXserver
|
||||
import HXcam
|
||||
import HXlcd
|
||||
import HXdb
|
||||
import time
|
||||
import smbus
|
||||
import sys
|
||||
import threading
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
|
||||
# MAIN CLASS
|
||||
class HXbotClass():
|
||||
|
||||
def __init__(self):
|
||||
super(HXbotClass, self).__init__()
|
||||
|
||||
self.i2c_bus = None
|
||||
self.hxpower = None
|
||||
self.reflex = None
|
||||
self.server = None
|
||||
|
||||
self.joystick = None
|
||||
self.hxcam = None
|
||||
self.hxlcd = None
|
||||
self.hxdb = None
|
||||
self.light = None
|
||||
self.sound = None
|
||||
self.log = None
|
||||
|
||||
self.status = HX.STATUS_INIT
|
||||
|
||||
self.hxpower_lock = threading.Lock()
|
||||
self.reflex_lock = threading.Lock()
|
||||
self.hxlcd_lock = threading.Lock()
|
||||
self.hxdb_lock = threading.Lock()
|
||||
|
||||
def get_ready(self):
|
||||
result = HX.OK_RSP
|
||||
|
||||
# Init I2C bus
|
||||
try:
|
||||
self.i2c_bus = smbus.SMBus(HX.I2C_BUS_NUMBER)
|
||||
except IOError:
|
||||
self.stop()
|
||||
return result | HX.I2C_BUS_ERR
|
||||
|
||||
# Init hxpower
|
||||
try:
|
||||
self.hxpower = HXpower.HXpowerClass(self.i2c_bus, self.hxpower_lock)
|
||||
except IOError:
|
||||
self.stop()
|
||||
return result | HX.HXPOWER_ERR
|
||||
|
||||
# Init reflex
|
||||
try:
|
||||
self.reflex = REflex.REflexClass(self)
|
||||
except IOError:
|
||||
self.stop()
|
||||
return result | HX.REFLEX_ERR
|
||||
|
||||
# Init server
|
||||
try:
|
||||
self.server = HXserver.HXserverClass(self)
|
||||
except OSError:
|
||||
self.stop()
|
||||
return result | HX.SERVER_ERR
|
||||
|
||||
# Init joystick
|
||||
try:
|
||||
self.joystick = HXjoystick.HXjoystickClass()
|
||||
except OSError:
|
||||
#self.joystick.stop()
|
||||
#self.joystick = None
|
||||
result |= HX.JOYSTICK_WRN
|
||||
|
||||
# Init hxcam
|
||||
try:
|
||||
self.hxcam = HXcam.HXcamClass()
|
||||
except OSError:
|
||||
self.hxcam.stop()
|
||||
self.hxcam = None
|
||||
result |= HX.HXCAMERA_WRN
|
||||
|
||||
# Init hxlcd
|
||||
try:
|
||||
self.hxlcd = HXlcd.HXlcdClass(self.i2c_bus, self.hxlcd_lock)
|
||||
except OSError:
|
||||
self.hxlcd.stop()
|
||||
self.hxlcd = None
|
||||
result |= HX.HXLCD_WRN
|
||||
|
||||
# Init hxdb
|
||||
try:
|
||||
self.hxdb = HXdb.HXdbClass(self)
|
||||
except Exception:
|
||||
#self.hxdb.stop()
|
||||
self.hxdb = None
|
||||
result |= HX.HXDB_WRN
|
||||
|
||||
# Init GPIO
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
#GPIO.setup(25, GPIO.OUT)
|
||||
|
||||
# Set status
|
||||
self.status = True
|
||||
|
||||
return result
|
||||
|
||||
def start(self):
|
||||
if self.status != HX.STATUS_READY:
|
||||
return HX.BLK_RSP
|
||||
|
||||
# Start hxpower
|
||||
self.hxpower.start()
|
||||
|
||||
# Start reflex
|
||||
self.reflex.start()
|
||||
|
||||
# Start server
|
||||
self.server.start()
|
||||
|
||||
# Start joystick
|
||||
if self.joystick is not None:
|
||||
self.joystick.start()
|
||||
|
||||
# Start camera
|
||||
if self.hxcam is not None:
|
||||
self.hxcam.start()
|
||||
|
||||
# Start lcd
|
||||
if self.hxlcd is not None:
|
||||
self.hxlcd.start()
|
||||
|
||||
# Start db
|
||||
if self.hxdb is not None:
|
||||
self.hxdb.start()
|
||||
|
||||
self.status = HX.STATUS_RUNNING
|
||||
|
||||
return HX.OK_RSP
|
||||
|
||||
def stop(self):
|
||||
# Disable MV
|
||||
self.hxpower.disable_mv()
|
||||
|
||||
# Disable camera
|
||||
if self.hxcam:
|
||||
# Stop process
|
||||
if self.hxcam.is_running:
|
||||
self.hxcam.stop()
|
||||
# Clear property
|
||||
self.hxcam = None
|
||||
|
||||
# Stop reflex
|
||||
if self.reflex:
|
||||
# Stop process
|
||||
if self.reflex.is_running:
|
||||
self.reflex.stop()
|
||||
# Clear property
|
||||
self.reflex = None
|
||||
|
||||
# Stop joystick
|
||||
if self.joystick:
|
||||
# Stop process
|
||||
if self.joystick.is_running:
|
||||
self.joystick.stop()
|
||||
# Clear property
|
||||
self.joystick = None
|
||||
|
||||
# Stop server
|
||||
if self.server:
|
||||
# Stop process
|
||||
if self.server.is_running:
|
||||
self.server.stop()
|
||||
# Clear property
|
||||
self.server = None
|
||||
|
||||
# Stop hxpower
|
||||
if self.hxpower:
|
||||
# Stop process
|
||||
if self.hxpower.is_running:
|
||||
self.hxpower.stop()
|
||||
# Clear property
|
||||
self.hxpower = None
|
||||
|
||||
# Stop hxlcd
|
||||
if self.hxlcd:
|
||||
# Stop process
|
||||
if self.hxlcd.is_running:
|
||||
self.hxlcd.stop()
|
||||
# Clear property
|
||||
self.hxlcd = None
|
||||
|
||||
# Stop hxdb
|
||||
if self.hxdb:
|
||||
# Stop process
|
||||
if self.hxdb.is_running:
|
||||
self.hxdb.stop()
|
||||
# Clear property
|
||||
self.hxdb = None
|
||||
|
||||
# Close I2C bus
|
||||
if self.i2c_bus:
|
||||
self.i2c_bus.close()
|
||||
# Clear property
|
||||
self.i2c_bus = None
|
||||
|
||||
# Set status
|
||||
self.status = HX.STATUS_STOP
|
||||
|
||||
GPIO.cleanup()
|
||||
|
||||
return HX.OK_RSP
|
||||
|
||||
def get_temp(self):
|
||||
try:
|
||||
F = open("/sys/class/thermal/thermal_zone0/temp", "r")
|
||||
T = float(F.read())
|
||||
except IOError:
|
||||
return -999
|
||||
finally:
|
||||
F.close()
|
||||
|
||||
return T / 1000
|
||||
|
||||
|
||||
# MAIN PROGRAM
|
||||
def main():
|
||||
# INIT
|
||||
print("Hi! I'am HXbot. Let's fun!'")
|
||||
print("Type command or \"help\"")
|
||||
|
||||
# Create HXbot instance
|
||||
hxbot = HXbotClass()
|
||||
|
||||
# Run
|
||||
start(hxbot)
|
||||
|
||||
# MAIN LOOP
|
||||
while True:
|
||||
# Set command line view
|
||||
if hxbot.status == HX.STATUS_INIT:
|
||||
command_view = "INIT>"
|
||||
elif hxbot.status == HX.STATUS_READY:
|
||||
command_view = "READY>"
|
||||
elif hxbot.status == HX.STATUS_RUNNING:
|
||||
command_view = "RUNNING>"
|
||||
elif hxbot.status == HX.STATUS_STOP:
|
||||
command_view = "STOP>"
|
||||
elif hxbot.status == HX.STATUS_EXIT:
|
||||
command_view = "EXIT>"
|
||||
|
||||
command = input(command_view)
|
||||
|
||||
# COMMANDS
|
||||
# Help
|
||||
if command.lower() == "help":
|
||||
print_help()
|
||||
|
||||
# Exit / Quit
|
||||
elif command.lower() == "exit" or \
|
||||
command.lower() == "quit":
|
||||
stop(hxbot)
|
||||
hxbot.status = HX.STATUS_EXIT
|
||||
print("Exit...")
|
||||
sys.exit()
|
||||
|
||||
# Status
|
||||
elif command.lower() == "status":
|
||||
print_status(hxbot)
|
||||
# REflex control
|
||||
elif command.lower() == "reflex":
|
||||
reflex_control(hxbot)
|
||||
# HXpower control
|
||||
elif command.lower() == "hxpower":
|
||||
hxpower_control(hxbot)
|
||||
# HXcam control
|
||||
elif command.lower() == "hxcam":
|
||||
hxcam_control(hxbot)
|
||||
|
||||
# Get ready
|
||||
elif command.lower() == "ready":
|
||||
ready(hxbot)
|
||||
# Start
|
||||
elif command.lower() == "start":
|
||||
start(hxbot)
|
||||
# Stop
|
||||
elif command.lower() == "stop":
|
||||
stop(hxbot)
|
||||
# Restart
|
||||
elif command.lower() == "restart":
|
||||
restart(hxbot)
|
||||
|
||||
# Test
|
||||
elif command.lower() == "t":
|
||||
t1 = time.clock()
|
||||
print("t1:", t1)
|
||||
time.sleep(5)
|
||||
t2 = time.clock()
|
||||
print("t2:", t2)
|
||||
dt = t2 - t1
|
||||
print("dt:", dt)
|
||||
|
||||
# WAT?
|
||||
else:
|
||||
print("WRONG COMMAND")
|
||||
print("Try again or type \"help\"")
|
||||
|
||||
# EXIT
|
||||
sys.exit()
|
||||
|
||||
|
||||
# FUNCTIONS
|
||||
def ready(hxbot):
|
||||
if hxbot.status != HX.STATUS_READY:
|
||||
print("Get ready...")
|
||||
result = hxbot.get_ready()
|
||||
print_result(result)
|
||||
else:
|
||||
print("HXbot already ready")
|
||||
|
||||
|
||||
def start(hxbot):
|
||||
if hxbot.status != HX.STATUS_RUNNING:
|
||||
if hxbot.status != HX.STATUS_READY:
|
||||
ready(hxbot)
|
||||
|
||||
print("Start...")
|
||||
result = hxbot.start()
|
||||
print_result(result)
|
||||
else:
|
||||
print("HXbot already running")
|
||||
|
||||
|
||||
def stop(hxbot):
|
||||
if hxbot.status != HX.STATUS_STOP:
|
||||
print("Stop...")
|
||||
result = hxbot.stop()
|
||||
print_result(result)
|
||||
else:
|
||||
print("HXbot already stopped")
|
||||
|
||||
|
||||
def restart(hxbot):
|
||||
stop(hxbot)
|
||||
ready(hxbot)
|
||||
start(hxbot)
|
||||
|
||||
|
||||
def print_help():
|
||||
print("This is HXbot main program. You can type this commands:")
|
||||
print("help - this help")
|
||||
print("exit |")
|
||||
print("quit - stop HXbot and exit")
|
||||
print("status - get status")
|
||||
print("start - start HXbot")
|
||||
print("stop - stop HXbot")
|
||||
print("restart - stop HXbot")
|
||||
print("reflex - control REflex")
|
||||
print("hxpower - control HXpower")
|
||||
|
||||
|
||||
def hxpower_help():
|
||||
print("This is HXpower control program. You can type this commands:")
|
||||
print("help - this help")
|
||||
print("exit - main menu")
|
||||
print("bt - switch BT")
|
||||
print("ba - switch BA")
|
||||
print("mv - enable/disable moving")
|
||||
print("us - enable/disable USB")
|
||||
print("0-255 - send raw command")
|
||||
|
||||
|
||||
def hxcam_help():
|
||||
print("This is HXcam control program. You can type this commands:")
|
||||
print("help - this help")
|
||||
print("exit - main menu")
|
||||
print("start - start HXcam")
|
||||
print("stop - stop HXcam")
|
||||
print("restart - restart HXcam")
|
||||
|
||||
|
||||
def reflex_help():
|
||||
print("This is REflex control program. You can type this commands:")
|
||||
print("help - this help")
|
||||
print("exit - main menu")
|
||||
print("0-255 - send raw command")
|
||||
|
||||
|
||||
def print_result(result):
|
||||
# Universal return codes
|
||||
if result == HX.OK_RSP:
|
||||
print("OK")
|
||||
elif result == HX.NO_RSP:
|
||||
print("WARNING: No response")
|
||||
elif result == HX.ERR_RSP:
|
||||
print("ERROR")
|
||||
elif result == HX.BLK_RSP:
|
||||
print("ERROR: Blocked")
|
||||
elif result == HX.CSE_RSP:
|
||||
print("ERROR: Wrong control sum")
|
||||
elif result == HX.BLK_RSP:
|
||||
print("ERROR: ")
|
||||
elif result == HX.IOE_RSP:
|
||||
print("ERROR: Input/output error")
|
||||
elif result == HX.TMO_RSP:
|
||||
print("ERROR: Timeout")
|
||||
|
||||
# HXbot extended return codes
|
||||
elif result == HX.I2C_BUS_ERR:
|
||||
print("ERROR: I2C bus not ready")
|
||||
elif result == HX.HXPOWER_ERR:
|
||||
print("ERROR: HXpower not ready")
|
||||
elif result == HX.JOYSTICK_WRN:
|
||||
print("WARNING: Joystick not found")
|
||||
elif result == HX.REFLEX_ERR:
|
||||
print("ERROR: REflex not ready")
|
||||
elif result == HX.SERVER_ERR:
|
||||
print("ERROR: Server not ready")
|
||||
elif result == HX.HXCAMERA_WRN:
|
||||
print("WARNING: Camera not ready")
|
||||
elif result == HX.HXLCD_WRN:
|
||||
print("WARNING: LCD module not ready")
|
||||
elif result == HX.HXDB_WRN:
|
||||
print("WARNING: DB module not ready")
|
||||
|
||||
# Unknown return code
|
||||
else:
|
||||
print("WARNING: Unknown return code received")
|
||||
|
||||
|
||||
def print_status(hxbot):
|
||||
if (hxbot.status != HX.STATUS_READY and
|
||||
hxbot.status != HX.STATUS_RUNNING):
|
||||
print("HXbot is not in ready or running state!")
|
||||
return
|
||||
|
||||
# Print voltages
|
||||
print("Vcc =", hxbot.hxpower.vcc)
|
||||
print("Vin =", hxbot.hxpower.vin)
|
||||
print("Vdc =", hxbot.hxpower.vdc)
|
||||
print("Vbt =", hxbot.hxpower.vbt)
|
||||
print("Vba =", hxbot.hxpower.vba)
|
||||
print("Vpf =", hxbot.hxpower.vpf)
|
||||
print("Vzu =", hxbot.hxpower.vzu)
|
||||
|
||||
# Print currents
|
||||
print("Abt =", hxbot.hxpower.abt)
|
||||
print("Aba =", hxbot.hxpower.aba)
|
||||
print("Ain =", hxbot.hxpower.ain)
|
||||
print("Ahx =", hxbot.hxpower.ahx)
|
||||
|
||||
# Print temperature
|
||||
print("CPU Temp:", hxbot.get_temp())
|
||||
print("REflex Temp:", hxbot.reflex.get_temp())
|
||||
#print("HXPower Temp:", )
|
||||
|
||||
# Print status
|
||||
if hxbot.hxpower.vcc_ok:
|
||||
print("Vcc - OK")
|
||||
else:
|
||||
print("Vcc - FAIL")
|
||||
if hxbot.hxpower.vin_ok:
|
||||
print("Vin - OK")
|
||||
else:
|
||||
print("Vin - FAIL")
|
||||
if hxbot.hxpower.vdc_ok:
|
||||
print("Vdc - OK")
|
||||
else:
|
||||
print("Vdc - FAIL")
|
||||
if hxbot.hxpower.vbt_ok:
|
||||
print("Vbt - OK")
|
||||
else:
|
||||
print("Vbt - FAIL")
|
||||
if hxbot.hxpower.vba_ok:
|
||||
print("Vba - OK")
|
||||
else:
|
||||
print("Vba - FAIL")
|
||||
if hxbot.hxpower.vpf_ok:
|
||||
print("Vpf - OK")
|
||||
else:
|
||||
print("Vpf - FAIL")
|
||||
if hxbot.hxpower.vzu_ok:
|
||||
print("Vzu - OK")
|
||||
else:
|
||||
print("Vzu - FAIL")
|
||||
|
||||
if hxbot.hxpower.abt_ok:
|
||||
print("Abt - OK")
|
||||
else:
|
||||
print("Abt - FAIL")
|
||||
if hxbot.hxpower.aba_ok:
|
||||
print("Aba - OK")
|
||||
else:
|
||||
print("Aba - FAIL")
|
||||
if hxbot.hxpower.ain_ok:
|
||||
print("Ain - OK")
|
||||
else:
|
||||
print("Ain - FAIL")
|
||||
if hxbot.hxpower.ahx_ok:
|
||||
print("Ahx - OK")
|
||||
else:
|
||||
print("Ahx - FAIL")
|
||||
|
||||
if hxbot.hxpower.bt_enabled:
|
||||
print("BT enabled")
|
||||
else:
|
||||
print("BT disabled")
|
||||
if hxbot.hxpower.ba_enabled:
|
||||
print("BA enabled")
|
||||
else:
|
||||
print("BA disabled")
|
||||
if hxbot.hxpower.mv_enabled:
|
||||
print("mv enabled")
|
||||
else:
|
||||
print("PF disabled")
|
||||
if hxbot.hxpower.us_enabled:
|
||||
print("USB power enabled")
|
||||
else:
|
||||
print("USB power disabled")
|
||||
if hxbot.hxpower.bt_blocked:
|
||||
print("BT blocked")
|
||||
else:
|
||||
print("BT unblocked")
|
||||
if hxbot.hxpower.ba_blocked:
|
||||
print("BA blocked")
|
||||
else:
|
||||
print("BA unblocked")
|
||||
|
||||
if hxbot.hxpower.in_plugged:
|
||||
print("IN plugged")
|
||||
else:
|
||||
print("IN unplugged")
|
||||
|
||||
if hxbot.hxpower.bt_full:
|
||||
print("BT charge complete")
|
||||
if hxbot.hxpower.ba_full:
|
||||
print("BA charge complete")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def reflex_control(hxbot):
|
||||
if (hxbot.status != HX.STATUS_READY and
|
||||
hxbot.status != HX.STATUS_RUNNING):
|
||||
print("HXbot is not in ready or running state!")
|
||||
return
|
||||
|
||||
rawCommand = 0x00
|
||||
rawResponse = 0x00
|
||||
|
||||
print("Reflex control program. Type command or \"help\"")
|
||||
print("Type \"exit\" to previous menu")
|
||||
command_view = "REflex control>"
|
||||
|
||||
while True:
|
||||
command = input(command_view)
|
||||
if command.lower() == "exit":
|
||||
break
|
||||
elif command.lower() == "help":
|
||||
reflex_help()
|
||||
else:
|
||||
# Try to send RAW command to REflex
|
||||
try:
|
||||
rawCommand = int(command)
|
||||
except:
|
||||
rawCommand = 0x00
|
||||
|
||||
if not rawCommand:
|
||||
continue
|
||||
|
||||
with hxbot.reflex_lock:
|
||||
hxbot.i2c_bus.write_byte(HX.REFLEX_ADDRESS, rawCommand)
|
||||
print("Sent: ", rawCommand)
|
||||
time.sleep(HX.REFLEX_RESPONSE_DELAY)
|
||||
rawResponse = hxbot.i2c_bus.read_byte(HX.REFLEX_ADDRESS)
|
||||
print("Received: ", rawResponse)
|
||||
|
||||
|
||||
def hxpower_control(hxbot):
|
||||
if (hxbot.status != HX.STATUS_READY and
|
||||
hxbot.status != HX.STATUS_RUNNING):
|
||||
print("HXbot is not in ready or running state!")
|
||||
return
|
||||
|
||||
rawCommand = 0x00
|
||||
rawResponse = 0x00
|
||||
|
||||
print("HXpower control program. Type command or \"help\"")
|
||||
print("Type \"exit\" to previous menu")
|
||||
command_view = "HXpower control>"
|
||||
|
||||
while True:
|
||||
command = input(command_view)
|
||||
if command.lower() == "exit":
|
||||
break
|
||||
elif command.lower() == "help":
|
||||
hxpower_help()
|
||||
elif command.lower() == "bt":
|
||||
if hxbot.hxpower.bt_enabled:
|
||||
print("Disable BT...")
|
||||
result = hxbot.hxpower.disable_bt()
|
||||
else:
|
||||
print("Enable BT...")
|
||||
result = hxbot.hxpower.enable_bt()
|
||||
print_result(result)
|
||||
elif command.lower() == "ba":
|
||||
if hxbot.hxpower.ba_enabled:
|
||||
print("Disable BA...")
|
||||
result = hxbot.hxpower.disable_ba()
|
||||
else:
|
||||
print("Enable BA...")
|
||||
result = hxbot.hxpower.enable_ba()
|
||||
print_result(result)
|
||||
elif command.lower() == "mv":
|
||||
if hxbot.hxpower.mv_enabled:
|
||||
print("Disable MV...")
|
||||
result = hxbot.hxpower.disable_mv()
|
||||
else:
|
||||
print("Enable MV...")
|
||||
result = hxbot.hxpower.enable_mv()
|
||||
print_result(result)
|
||||
elif command.lower() == "us":
|
||||
if hxbot.hxpower.us_enabled:
|
||||
print("Disable USB power...")
|
||||
result = hxbot.hxpower.disable_us()
|
||||
else:
|
||||
print("Enable USB power...")
|
||||
result = hxbot.hxpower.enable_us()
|
||||
print_result(result)
|
||||
elif command.lower() == "reset":
|
||||
GPIO.output(25, 0)
|
||||
time.sleep(5)
|
||||
GPIO.output(25, 1)
|
||||
else:
|
||||
# Try to send RAW command to HXpower
|
||||
try:
|
||||
rawCommand = int(command)
|
||||
except:
|
||||
rawCommand = 0x00
|
||||
print("Wrong command!")
|
||||
|
||||
if not rawCommand:
|
||||
continue
|
||||
|
||||
rawCommand = (rawCommand << 8) | (rawCommand ^ HX.XOR_SEQ)
|
||||
try:
|
||||
with hxbot.hxpower_lock:
|
||||
hxbot.i2c_bus.write_word_data(HX.POWER_ADDRESS,
|
||||
HX.EXT_COM, rawCommand)
|
||||
print("Sent:", rawCommand, "(", rawCommand, ")")
|
||||
time.sleep(HX.POWER_RESPONSE_DELAY)
|
||||
rawResponse = hxbot.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
print("Received:", rawResponse)
|
||||
except IOError as E:
|
||||
print(E)
|
||||
|
||||
|
||||
def hxcam_control(hxbot):
|
||||
if (hxbot.status != HX.STATUS_READY and
|
||||
hxbot.status != HX.STATUS_RUNNING):
|
||||
print("HXbot is not in ready or running state!")
|
||||
return
|
||||
|
||||
print("HXcam control program. Type command or \"help\"")
|
||||
print("Type \"exit\" to previous menu")
|
||||
command_view = "HXcam control>"
|
||||
|
||||
while True:
|
||||
command = input(command_view)
|
||||
if command.lower() == "exit":
|
||||
break
|
||||
elif command.lower() == "help":
|
||||
hxcam_help()
|
||||
elif command.lower() == "start":
|
||||
print("Start HXcam")
|
||||
if hxbot.hxcam.is_running:
|
||||
print("Allready running")
|
||||
else:
|
||||
hxbot.hxcam.start()
|
||||
elif command.lower() == "stop":
|
||||
print("Stop HXcam")
|
||||
if not hxbot.hxcam.is_running:
|
||||
print("Not running")
|
||||
else:
|
||||
hxbot.hxcam.stop()
|
||||
elif command.lower() == "restart":
|
||||
print("Restart HXcam")
|
||||
if hxbot.hxcam.is_running:
|
||||
print("Stop...")
|
||||
hxbot.hxcam.stop()
|
||||
if not hxbot.hxcam.is_running:
|
||||
print("Start...")
|
||||
hxbot.hxcam.start()
|
||||
|
||||
# MAIN PROGRAM
|
||||
if __name__ == "__main__":
|
||||
main()
|
257
HXbot/HXcam.py
Executable file
257
HXbot/HXcam.py
Executable file
@ -0,0 +1,257 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot camera control module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import subprocess
|
||||
import threading
|
||||
#import select
|
||||
import time
|
||||
import sys
|
||||
import os.path as path
|
||||
import HX
|
||||
|
||||
|
||||
class HXcamClass():
|
||||
|
||||
def __init__(self):
|
||||
super(HXcamClass, self).__init__()
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.mcam = None
|
||||
self.rcam = None
|
||||
self.mmic = None
|
||||
self.rvid = None
|
||||
|
||||
self.is_running = False
|
||||
|
||||
# Subprocess states
|
||||
# 0 - Not running
|
||||
# 1 - Running
|
||||
# 2 - Error
|
||||
# 3 - Device not found
|
||||
self.mcam_state = HX.CAM_STATE_STP
|
||||
self.rvid_state = HX.CAM_STATE_STP
|
||||
self.rcam_state = HX.CAM_STATE_STP
|
||||
self.mmic_state = HX.CAM_STATE_STP
|
||||
|
||||
self.mcam_wrn_count = 0
|
||||
self.rcam_wrn_count = 0
|
||||
self.mmic_wrn_count = 0
|
||||
|
||||
def start(self):
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.mcam_start()
|
||||
#self.rcam_start()
|
||||
self.mmic_start()
|
||||
|
||||
self.__t.start()
|
||||
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.mcam_stop()
|
||||
#self.rcam_stop()
|
||||
self.mmic_stop()
|
||||
|
||||
self.is_running = False
|
||||
|
||||
def restart(self):
|
||||
if self.is_running:
|
||||
self.__stop()
|
||||
self.__start()
|
||||
|
||||
def test(self):
|
||||
#import time
|
||||
#import sys
|
||||
#import shlex
|
||||
#string = ""
|
||||
#args = shlex.split(string)
|
||||
#print(args)
|
||||
#sys.exit()
|
||||
pass
|
||||
|
||||
def mcam_start(self):
|
||||
# cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15'
|
||||
# --sout '#rtp{sdp=rtsp://:8554/video}' -v --live-caching 50
|
||||
if path.exists('/dev/video0'):
|
||||
arg = 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15'
|
||||
elif path.exists('/dev/video1'):
|
||||
arg = 'v4l2:///dev/video1:chroma=H264:width=1280:height=720:fps=15'
|
||||
else:
|
||||
self.mcam_state = HX.CAM_STATE_ERR
|
||||
return
|
||||
|
||||
self.mcam = subprocess.Popen(
|
||||
args=['/usr/bin/cvlc',
|
||||
arg,
|
||||
'--sout', '#rtp{sdp=rtsp://:8554/video}',
|
||||
'--live-caching', '50', 'vlc://quit'],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
self.mcam_state = HX.CAM_STATE_RUN
|
||||
|
||||
def mcam_stop(self):
|
||||
if self.mcam_state != HX.CAM_STATE_ERR:
|
||||
self.mcam.terminate()
|
||||
self.mcam_state = HX.CAM_STATE_STP
|
||||
|
||||
def rcam_start(self):
|
||||
# raspivid -t 0 -n -w 1280 -h 720 -fps 15 -o - |
|
||||
# cvlc -v stream:///dev/stdin
|
||||
# --sout '#rtp{sdp=rtsp://:8555/video}' :demux=h264
|
||||
self.rvid = subprocess.Popen(
|
||||
args=['raspivid', '-t', '0', '-n', '-w', '1280', '-h', '720',
|
||||
'-fps', '15', '-o', '-'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
self.rcam = subprocess.Popen(
|
||||
args=['cvlc', 'stream:///dev/stdin', '--sout',
|
||||
'#rtp{sdp=rtsp://:8555/video}', ':demux=h264',
|
||||
'--live-caching', '50', 'vlc://quit'],
|
||||
stdin=self.rvid.stdout,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
self.rcam_state = HX.CAM_STATE_RUN
|
||||
|
||||
def rcam_stop(self):
|
||||
if self.rcam_state != HX.CAM_STATE_ERR:
|
||||
self.rvid.terminate()
|
||||
self.rcam.terminate()
|
||||
self.rcam_state = HX.CAM_STATE_STP
|
||||
|
||||
def mmic_start(self):
|
||||
# cvlc -v 'alsa://hw:1,0'
|
||||
# --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}
|
||||
# :rtp{sdp=rtsp://:8556/audio}'
|
||||
self.mmic = subprocess.Popen(
|
||||
args=['cvlc', 'alsa://hw:0,0', '--sout',
|
||||
'#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}' +
|
||||
':rtp{sdp=rtsp://:8556/audio}',
|
||||
'--live-caching', '500', 'vlc://quit'],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
self.mmic_state = HX.CAM_STATE_RUN
|
||||
|
||||
def mmic_stop(self):
|
||||
if self.mmic_state != HX.CAM_STATE_ERR:
|
||||
self.mmic.terminate()
|
||||
self.mmic_state = HX.CAM_STATE_STP
|
||||
|
||||
def __process(self, stopRequest):
|
||||
# Process loop
|
||||
while not stopRequest.is_set():
|
||||
# Main Camera
|
||||
if self.mcam_state != HX.CAM_STATE_ERR:
|
||||
if self.mcam.poll() is not None:
|
||||
self.mcam_start()
|
||||
|
||||
if self.mcam_state != HX.CAM_STATE_WRN:
|
||||
self.mcam_wrn_count += 1
|
||||
|
||||
if self.mcam_wrn_count >= HX.CAM_MAX_WRN_COUNT:
|
||||
self.mcam_state = HX.CAM_STATE_WRN
|
||||
|
||||
# Rear Camera
|
||||
#if self.rcam_state != HX.CAM_STATE_ERR:
|
||||
#if self.rcam.poll() is not None:
|
||||
#self.rcam_start()
|
||||
|
||||
#if self.rcam_state != HX.CAM_STATE_WRN:
|
||||
#self.rcam_wrn_count += 1
|
||||
|
||||
#if self.rcam_wrn_count >= HX.CAM_MAX_WRN_COUNT:
|
||||
#self.rcam_state = HX.CAM_STATE_WRN
|
||||
|
||||
# Main Microphone
|
||||
if self.mmic_state != HX.CAM_STATE_ERR:
|
||||
if self.mmic.poll() is not None:
|
||||
self.mmic_start()
|
||||
|
||||
if self.mmic_state != HX.CAM_STATE_WRN:
|
||||
self.mmic_wrn_count += 1
|
||||
|
||||
if self.mmic_wrn_count >= HX.CAM_MAX_WRN_COUNT:
|
||||
self.mmic_state = HX.CAM_STATE_WRN
|
||||
|
||||
time.sleep(HX.CAM_DELAY)
|
||||
|
||||
#if self.mcam_state == 1:
|
||||
## VLC-1
|
||||
#r, w, e = select.select([self.mcam.stderr], [], [], 0.5)
|
||||
#if self.mcam.stderr in r:
|
||||
#print("VLC-1 ERROR:")
|
||||
#print(self.mcam.stderr.readline())
|
||||
|
||||
#r, w, e = select.select([self.mcam.stdout], [], [], 0.5)
|
||||
#if self.mcam.stdout in r:
|
||||
#print("VLC-1 OUT:")
|
||||
#print(self.mcam.stdout.readline())
|
||||
|
||||
#if self.rvid_state == 1:
|
||||
## VLC-2
|
||||
#r, w, e = select.select([self.rvid.stderr], [], [], 0.5)
|
||||
#if self.rvid.stderr in r:
|
||||
#print("RVID ERROR:")
|
||||
#print(self.rvid.stderr.readline())
|
||||
|
||||
#r, w, e = select.select([self.rcam.stderr], [], [], 0.5)
|
||||
#if self.rcam.stderr in r:
|
||||
#print("VLC-2 ERROR:")
|
||||
#print(self.rcam.stderr.readline())
|
||||
|
||||
#r, w, e = select.select([self.rcam.stdout], [], [], 0.5)
|
||||
#if self.rcam.stdout in r:
|
||||
#print("VLC-2 OUT:")
|
||||
#print(self.rcam.stdout.readline())
|
||||
|
||||
#if self.mmic_state == 1:
|
||||
## VLC-3
|
||||
#r, w, e = select.select([self.mmic.stderr], [], [], 0)
|
||||
#if self.mmic.stderr in r:
|
||||
#print("MMIC ERROR:")
|
||||
#print(self.mmic.stderr.readline())
|
||||
|
||||
#r, w, e = select.select([self.mmic.stdout], [], [], 0.5)
|
||||
#if self.mmic.stdout in r:
|
||||
#print("MMIC OUT:")
|
||||
#print(self.mmic.stdout.readline())
|
||||
|
||||
|
||||
def main():
|
||||
HXcam = HXcamClass()
|
||||
HXcam.start()
|
||||
|
||||
print("Execution started")
|
||||
|
||||
command_view = '"Return" or CTRL+C to exit>'
|
||||
try:
|
||||
while True:
|
||||
command = input(command_view)
|
||||
|
||||
if command == "":
|
||||
HXcam.stop()
|
||||
sys.exit()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Terminate...")
|
||||
HXcam.stop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
132
HXbot/HXdb.py
Executable file
132
HXbot/HXdb.py
Executable file
@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot database module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import threading
|
||||
import time
|
||||
import mysql.connector
|
||||
from mysql.connector import errorcode
|
||||
|
||||
|
||||
class HXdbClass():
|
||||
|
||||
def __init__(self, hxbot):
|
||||
super(HXdbClass, self).__init__()
|
||||
|
||||
self.hxbot = hxbot
|
||||
|
||||
self.hxpower = None
|
||||
self.reflex = None
|
||||
self.joystick = None
|
||||
self.hxlcd = None
|
||||
self.hxcam = None
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.is_running = False
|
||||
|
||||
try:
|
||||
self.cnx = mysql.connector.connect(user=HX.DB_USER,
|
||||
password=HX.DB_PASS,
|
||||
host=HX.DB_HOST,
|
||||
database=HX.DB_NAME)
|
||||
except mysql.connector.Error as err:
|
||||
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
|
||||
print("Something is wrong with your user name or password")
|
||||
elif err.errno == errorcode.ER_BAD_DB_ERROR:
|
||||
print("Database does not exist")
|
||||
else:
|
||||
print(err)
|
||||
self.cnx = None
|
||||
|
||||
raise
|
||||
|
||||
def start(self):
|
||||
self.hxpower = self.hxbot.hxpower
|
||||
self.reflex = self.hxbot.reflex
|
||||
self.joystick = self.hxbot.joystick
|
||||
self.hxlcd = self.hxbot.hxlcd
|
||||
self.hxcam = self.hxbot.hxcam
|
||||
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
if self.cnx is not None:
|
||||
self.cnx.close()
|
||||
|
||||
self.hxpower = None
|
||||
self.reflex = None
|
||||
self.joystick = None
|
||||
self.hxlcd = None
|
||||
self.hxcam = None
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
def __process(self, stopRequest):
|
||||
cursor = self.cnx.cursor()
|
||||
pw = self.hxpower
|
||||
|
||||
insert_state = ("INSERT INTO states "
|
||||
"(vcc, vin, vdc, vbt, vba, vis, vzu, "
|
||||
"ahx, aba, ain, adc, "
|
||||
"vcc_ok, vin_ok, vdc_ok, vbt_ok, vba_ok, "
|
||||
"vis_ok, vzu_ok, "
|
||||
"ahx_ok, aba_ok, ain_ok, adc_ok, "
|
||||
"lr_enabled, ba_enabled, ba_blocked, "
|
||||
"vcc_low, vcc_high, vin_low, vin_high, "
|
||||
"vdc_low, vdc_high, vbt_low, vbt_full, "
|
||||
"vba_low, vba_full, vis_low, vis_high, "
|
||||
"vzu_low, vzu_high, "
|
||||
"ahx_low, ahx_high, aba_low, aba_high, "
|
||||
"ain_low, ain_high, adc_low, adc_high, "
|
||||
"pf_enabled, bl_enabled, bl_powered, "
|
||||
"bl_error, ba_full, ba_charge) "
|
||||
"VALUES ("
|
||||
"%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, "
|
||||
"%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, "
|
||||
"%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, "
|
||||
"%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, "
|
||||
"%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, "
|
||||
"%s, %s, %s)")
|
||||
|
||||
while not stopRequest.is_set():
|
||||
# Get Data
|
||||
state = (pw.vcc, pw.vin, pw.vdc, pw.vbt, pw.vba, pw.vis,
|
||||
pw.vzu, pw.ahx, pw.aba, pw.ain, pw.adc, pw.vcc_ok,
|
||||
pw.vin_ok, pw.vdc_ok, pw.vbt_ok, pw.vba_ok,
|
||||
pw.vis_ok, pw.vzu_ok,
|
||||
pw.ahx_ok, pw.aba_ok, pw.ain_ok, pw.adc_ok,
|
||||
pw.lr_enabled, pw.ba_enabled, pw.ba_blocked,
|
||||
pw.vcc_low, pw.vcc_high, pw.vin_low, pw.vin_high,
|
||||
pw.vdc_low, pw.vdc_high, pw.vbt_low, pw.vbt_full,
|
||||
pw.vba_low, pw.vba_full, pw.vis_low, pw.vis_high,
|
||||
pw.vzu_low, pw.vzu_high, pw.ahx_low, pw.ahx_high,
|
||||
pw.aba_low, pw.aba_high, pw.ain_low, pw.ain_high,
|
||||
pw.adc_low, pw.adc_high,
|
||||
pw.pf_enabled, pw.bl_enabled,
|
||||
pw.bl_powered, pw.bl_error,
|
||||
pw.ba_full, pw.ba_charge)
|
||||
|
||||
# Insert Data
|
||||
if pw.online:
|
||||
cursor.execute(insert_state, state)
|
||||
self.cnx.commit()
|
||||
|
||||
# Delay
|
||||
time.sleep(HX.DB_DELAY)
|
||||
|
||||
cursor.close()
|
234
HXbot/HXjoystick.py
Executable file
234
HXbot/HXjoystick.py
Executable file
@ -0,0 +1,234 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot controller module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import threading
|
||||
import array
|
||||
import struct
|
||||
import select
|
||||
import time
|
||||
from fcntl import ioctl
|
||||
|
||||
|
||||
class HXjoystickClass():
|
||||
|
||||
def __init__(self):
|
||||
super(HXjoystickClass, self).__init__()
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
self.ready = False
|
||||
|
||||
self.device = open(HX.JOYSTICK_PATH, 'rb')
|
||||
|
||||
self.name = ""
|
||||
self.axis_states = {}
|
||||
self.button_states = {}
|
||||
self.axis_map = []
|
||||
self.button_map = []
|
||||
self.axis_names = HX.JOYSTICK_AXIS_NAMES
|
||||
self.button_names = HX.JOYSTICK_BUTTON_NAMES
|
||||
|
||||
self.online = False
|
||||
self.is_running = False
|
||||
self.last_command_time = 0.0
|
||||
|
||||
# Get the device name.
|
||||
buf = array.array('B', [0] * 64)
|
||||
# JSIOCGNAME(len)
|
||||
ioctl(self.device, 0x80006a13 + (0x10000 * len(buf)), buf)
|
||||
self.name = buf.tostring()
|
||||
#print('Device name: %s' % js_name)
|
||||
|
||||
# Get number of axes and buttons.
|
||||
buf = array.array('B', [0])
|
||||
ioctl(self.device, 0x80016a11, buf) # JSIOCGAXES
|
||||
num_axes = buf[0]
|
||||
|
||||
buf = array.array('B', [0])
|
||||
ioctl(self.device, 0x80016a12, buf) # JSIOCGBUTTONS
|
||||
num_buttons = buf[0]
|
||||
|
||||
# Get the axis map.
|
||||
buf = array.array('B', [0] * 0x40)
|
||||
ioctl(self.device, 0x80406a32, buf) # JSIOCGAXMAP
|
||||
|
||||
for axis in buf[:num_axes]:
|
||||
axis_name = self.axis_names.get(axis, 'unknown(0x%02x)' % axis)
|
||||
self.axis_map.append(axis_name)
|
||||
self.axis_states[axis_name] = 0.0
|
||||
|
||||
# Get the button map.
|
||||
buf = array.array('H', [0] * 200)
|
||||
ioctl(self.device, 0x80406a34, buf) # JSIOCGBTNMAP
|
||||
|
||||
for btn in buf[:num_buttons]:
|
||||
btn_name = self.button_names.get(btn, 'unknown(0x%03x)' % btn)
|
||||
self.button_map.append(btn_name)
|
||||
self.button_states[btn_name] = 0
|
||||
|
||||
#print('%d axes found: %s' % (num_axes, ', '.join(self.axis_map)))
|
||||
#print('%d btns found: %s' % (num_buttons, ', '.join(self.button_map)))
|
||||
|
||||
def start(self):
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
def __process(self, stopRequest):
|
||||
while not stopRequest.is_set():
|
||||
r, w, e = select.select([self.device], [], [], 0.8)
|
||||
if self.device in r:
|
||||
try:
|
||||
evbuf = self.device.read(8)
|
||||
self.online = True
|
||||
except OSError:
|
||||
self.online = False
|
||||
self.ready = False
|
||||
continue
|
||||
|
||||
if evbuf:
|
||||
time_, value, type, number = struct.unpack('IhBB', evbuf)
|
||||
|
||||
# Save last command time
|
||||
self.last_command_time = time.clock()
|
||||
|
||||
#if type & 0x80:
|
||||
#print("(initial)")
|
||||
|
||||
if type & 0x01:
|
||||
button = self.button_map[number]
|
||||
if button:
|
||||
self.button_states[button] = value
|
||||
#if value:
|
||||
#print("%s pressed" % (button))
|
||||
#else:
|
||||
#print("%s released" % (button))
|
||||
|
||||
if type & 0x02:
|
||||
axis = self.axis_map[number]
|
||||
if axis:
|
||||
fvalue = value / 32767.0
|
||||
self.axis_states[axis] = fvalue
|
||||
#print("%s: %.3f" % (axis, fvalue))
|
||||
|
||||
# Switch ready property
|
||||
if (self.button_states[HX.JOYSTICK_START_BTN_1] and
|
||||
self.button_states[HX.JOYSTICK_START_BTN_2]):
|
||||
if self.ready:
|
||||
self.ready = False
|
||||
else:
|
||||
self.ready = True
|
||||
|
||||
# Timeout? Relax...
|
||||
elif time.clock() - self.last_command_time >= \
|
||||
HX.JOYSTICK_READY_TIMEOUT / 100:
|
||||
self.ready = False
|
||||
|
||||
def get_m(self):
|
||||
axis_move = self.axis_states[HX.JOYSTICK_MOVE_AXIS]
|
||||
axis_steer = self.axis_states[HX.JOYSTICK_STEER_AXIS]
|
||||
|
||||
axis_head_v = self.axis_states[HX.JOYSTICK_HEAD_V_AXIS]
|
||||
axis_head_h = self.axis_states[HX.JOYSTICK_HEAD_H_AXIS]
|
||||
|
||||
# STOP (FLOAT)
|
||||
if (axis_move >= -1 / 8) and (axis_move <= 1 / 8):
|
||||
move = HX.MOVE_FLOAT
|
||||
|
||||
# MOVE FORWARD
|
||||
elif (axis_move >= -2 / 8) and (axis_move < -1 / 8):
|
||||
move = HX.MOVE_FWD1
|
||||
elif (axis_move >= -3 / 8) and (axis_move < -2 / 8):
|
||||
move = HX.MOVE_FWD2
|
||||
elif (axis_move >= -4 / 8) and (axis_move < -3 / 8):
|
||||
move = HX.MOVE_FWD3
|
||||
elif (axis_move >= -5 / 8) and (axis_move < -4 / 8):
|
||||
move = HX.MOVE_FWD4
|
||||
elif (axis_move >= -6 / 8) and (axis_move < -5 / 8):
|
||||
move = HX.MOVE_FWD5
|
||||
elif (axis_move >= -7 / 8) and (axis_move < -6 / 8):
|
||||
move = HX.MOVE_FWD6
|
||||
elif (axis_move >= -1) and (axis_move < -7 / 8):
|
||||
move = HX.MOVE_FWD7
|
||||
|
||||
# MOVE BACKWARD
|
||||
elif (axis_move > 1 / 8) and (axis_move <= 2 / 8):
|
||||
move = HX.MOVE_REV1
|
||||
elif (axis_move > 2 / 8) and (axis_move <= 3 / 8):
|
||||
move = HX.MOVE_REV2
|
||||
elif (axis_move > 3 / 8) and (axis_move <= 4 / 8):
|
||||
move = HX.MOVE_REV3
|
||||
elif (axis_move > 4 / 8) and (axis_move <= 5 / 8):
|
||||
move = HX.MOVE_REV4
|
||||
elif (axis_move > 5 / 8) and (axis_move <= 6 / 8):
|
||||
move = HX.MOVE_REV5
|
||||
elif (axis_move > 6 / 8) and (axis_move <= 7 / 8):
|
||||
move = HX.MOVE_REV6
|
||||
elif (axis_move > 7 / 8) and (axis_move <= 1):
|
||||
move = HX.MOVE_REV7
|
||||
|
||||
# CENTER (FLOAT)
|
||||
if (axis_steer >= -1 / 8) and (axis_steer <= 1 / 8):
|
||||
steer = HX.STEER_CENTER
|
||||
|
||||
# STEER LEFT
|
||||
elif (axis_steer >= -2 / 8) and (axis_steer < -1 / 8):
|
||||
steer = HX.STEER_LEFT1
|
||||
elif (axis_steer >= -3 / 8) and (axis_steer < -2 / 8):
|
||||
steer = HX.STEER_LEFT2
|
||||
elif (axis_steer >= -4 / 8) and (axis_steer < -3 / 8):
|
||||
steer = HX.STEER_LEFT3
|
||||
elif (axis_steer >= -5 / 8) and (axis_steer < -4 / 8):
|
||||
steer = HX.STEER_LEFT4
|
||||
elif (axis_steer >= -6 / 8) and (axis_steer < -5 / 8):
|
||||
steer = HX.STEER_LEFT5
|
||||
elif (axis_steer >= -7 / 8) and (axis_steer < -6 / 8):
|
||||
steer = HX.STEER_LEFT6
|
||||
elif (axis_steer >= -1) and (axis_steer < -7 / 8):
|
||||
steer = HX.STEER_LEFT7
|
||||
|
||||
# STEER RIGHT
|
||||
elif (axis_steer > 1 / 8) and (axis_steer <= 2 / 8):
|
||||
steer = HX.STEER_RIGHT1
|
||||
elif (axis_steer > 2 / 8) and (axis_steer <= 3 / 8):
|
||||
steer = HX.STEER_RIGHT2
|
||||
elif (axis_steer > 3 / 8) and (axis_steer <= 4 / 8):
|
||||
steer = HX.STEER_RIGHT3
|
||||
elif (axis_steer > 4 / 8) and (axis_steer <= 5 / 8):
|
||||
steer = HX.STEER_RIGHT4
|
||||
elif (axis_steer > 5 / 8) and (axis_steer <= 6 / 8):
|
||||
steer = HX.STEER_RIGHT5
|
||||
elif (axis_steer > 6 / 8) and (axis_steer <= 7 / 8):
|
||||
steer = HX.STEER_RIGHT6
|
||||
elif (axis_steer > 7 / 8) and (axis_steer <= 1):
|
||||
steer = HX.STEER_RIGHT7
|
||||
|
||||
# Head V
|
||||
if axis_head_v > 0:
|
||||
head_v = int(HX.HEAD_V_CENTER - HX.HEAD_V_UP_RANGE * axis_head_v)
|
||||
else:
|
||||
head_v = int(HX.HEAD_V_CENTER - HX.HEAD_V_DOWN_RANGE * axis_head_v)
|
||||
|
||||
# Head H
|
||||
if axis_head_h > 0:
|
||||
head_h = int(HX.HEAD_H_CENTER - HX.HEAD_H_R_RANGE * axis_head_h)
|
||||
else:
|
||||
head_h = int(HX.HEAD_H_CENTER - HX.HEAD_H_L_RANGE * axis_head_h)
|
||||
|
||||
# Return
|
||||
return (True, move, steer, head_v, head_h)
|
149
HXbot/HXlcd.py
Executable file
149
HXbot/HXlcd.py
Executable file
@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot LCD module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import threading
|
||||
import time
|
||||
import array
|
||||
import struct
|
||||
|
||||
|
||||
class HXlcdClass():
|
||||
|
||||
def __init__(self, i2c_bus, lock):
|
||||
super(HXlcdClass, self).__init__()
|
||||
|
||||
self.i2c_bus = i2c_bus
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.lock = lock
|
||||
self.online = False
|
||||
self.is_running = False
|
||||
self.error_count = 0
|
||||
|
||||
def start(self):
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
def __process(self, stopRequest):
|
||||
while not stopRequest.is_set():
|
||||
try:
|
||||
self.__send_command(HX.COM_PING)
|
||||
|
||||
self.online = True
|
||||
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
|
||||
# Too many errors
|
||||
if self.error_count >= HX.LCD_ERROR_LIMIT:
|
||||
self.online = False
|
||||
|
||||
# Delay
|
||||
time.sleep(HX.LCD_DELAY)
|
||||
|
||||
def __sum_check(self, val, sum_):
|
||||
tmp = 0x00
|
||||
for b in val:
|
||||
tmp ^= b
|
||||
tmp ^= HX.XOR_SEQ
|
||||
if tmp == sum_:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __read_float(self, cmd):
|
||||
# Byte array
|
||||
data = array.array('B', [0, 0, 0, 0])
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.LCD_RESPONSE_DELAY)
|
||||
|
||||
# Get bytes
|
||||
data[0] = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
data[1] = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
data[2] = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
data[3] = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
|
||||
# Get check sum
|
||||
sum_ = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
|
||||
# Check and return value
|
||||
if self.__sum_check(data, sum_):
|
||||
return struct.unpack('f', data)[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __read_byte(self, cmd):
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.LCD_RESPONSE_DELAY)
|
||||
|
||||
# Get byte
|
||||
data = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
|
||||
# Get check sum
|
||||
sum_ = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
|
||||
# Check and return value
|
||||
if data ^ HX.XOR_SEQ == sum_:
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
|
||||
def __write_byte(self, cmd):
|
||||
cmd = (cmd << 8) | (cmd ^ HX.XOR_SEQ)
|
||||
self.i2c_bus.write_word_data(HX.LCD_ADDRESS, HX.EXT_COM, cmd)
|
||||
|
||||
def send_cmd(self, cmd):
|
||||
try:
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.LCD_RESPONSE_DELAY)
|
||||
|
||||
# Get response
|
||||
response = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
|
||||
# Return
|
||||
return response
|
||||
except IOError:
|
||||
return HX.IOE_RSP
|
||||
|
||||
def __send_command(self, command):
|
||||
try:
|
||||
with self.lock:
|
||||
self.i2c_bus.write_word_data(HX.LCD_ADDRESS, command, 0)
|
||||
time.sleep(HX.LCD_RESPONSE_DELAY)
|
||||
response = self.i2c_bus.read_byte(HX.LCD_ADDRESS)
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
if self.error_count >= HX.LCD_ERROR_LIMIT:
|
||||
self.online = False
|
||||
return HX.IOE_RSP
|
||||
else:
|
||||
self.error_count = 0
|
||||
self.online = True
|
||||
return response
|
||||
|
||||
return HX.NO_RSP
|
1
HXbot/HXlight.py
Executable file
1
HXbot/HXlight.py
Executable file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
1
HXbot/HXlog.py
Executable file
1
HXbot/HXlog.py
Executable file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
587
HXbot/HXpower.py
Executable file
587
HXbot/HXpower.py
Executable file
@ -0,0 +1,587 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot power control module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import threading
|
||||
import time
|
||||
import array
|
||||
import struct
|
||||
|
||||
|
||||
class HXpowerClass():
|
||||
|
||||
def __init__(self, i2c_bus, lock):
|
||||
super(HXpowerClass, self).__init__()
|
||||
|
||||
self.i2c_bus = i2c_bus
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
self.lock = lock
|
||||
|
||||
# MV
|
||||
self.__mv_enable_time = 0.0
|
||||
self.mv_blocked = True
|
||||
|
||||
# HXpower data
|
||||
self.online = False
|
||||
self.is_running = False
|
||||
self.error_count = 0
|
||||
|
||||
self.status = 0x000000
|
||||
self.vcc = 0.0
|
||||
self.vin = 0.0
|
||||
self.vdc = 0.0
|
||||
self.vbt = 0.0
|
||||
self.vba = 0.0
|
||||
self.vpf = 0.0
|
||||
self.vzu = 0.0
|
||||
self.abt = 0.0
|
||||
self.aba = 0.0
|
||||
self.ain = 0.0
|
||||
self.ahx = 0.0
|
||||
self.vcc_ok = False
|
||||
self.vin_ok = False
|
||||
self.vdc_ok = False
|
||||
self.vbt_ok = False
|
||||
self.vba_ok = False
|
||||
self.vpf_ok = False
|
||||
self.vzu_ok = False
|
||||
self.abt_ok = False
|
||||
self.aba_ok = False
|
||||
self.ain_ok = False
|
||||
self.ahx_ok = False
|
||||
self.bt_enabled = False
|
||||
self.ba_enabled = False
|
||||
self.bt_blocked = False
|
||||
self.ba_blocked = False
|
||||
self.vcc_low = False
|
||||
self.vcc_high = False
|
||||
self.vin_low = False
|
||||
self.vin_high = False
|
||||
self.vdc_low = False
|
||||
self.vdc_high = False
|
||||
self.vbt_low = False
|
||||
self.vbt_full = False
|
||||
self.vba_low = False
|
||||
self.vba_full = False
|
||||
self.vpf_low = False
|
||||
self.vpf_high = False
|
||||
self.vzu_low = False
|
||||
self.vzu_high = False
|
||||
self.abt_low = False
|
||||
self.abt_high = False
|
||||
self.aba_low = False
|
||||
self.aba_high = False
|
||||
self.ain_low = False
|
||||
self.ain_high = False
|
||||
self.ahx_low = False
|
||||
self.ahx_high = False
|
||||
|
||||
self.mv_enabled = False
|
||||
self.us_enabled = False
|
||||
|
||||
self.in_plugged = False
|
||||
self.ba_full = False
|
||||
self.bt_full = False
|
||||
|
||||
def start(self):
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
def __process(self, stopRequest):
|
||||
stat1 = 0x00
|
||||
stat2 = 0x00
|
||||
stat3 = 0x00
|
||||
|
||||
# Process loop
|
||||
while not stopRequest.is_set():
|
||||
try:
|
||||
self.status = 0x0000
|
||||
|
||||
# Get status 1
|
||||
tmp = self.__read_byte(HX.COM_GET_STAT1)
|
||||
if tmp is not None:
|
||||
stat1 = tmp << 8
|
||||
else:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
|
||||
# Get status 2
|
||||
tmp = self.__read_byte(HX.COM_GET_STAT2)
|
||||
if tmp is not None:
|
||||
stat2 = tmp
|
||||
else:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
|
||||
# Get status 3
|
||||
tmp = self.__read_byte(HX.COM_GET_STAT3)
|
||||
if tmp is not None:
|
||||
stat3 = tmp << 16
|
||||
else:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
|
||||
self.status |= stat1
|
||||
self.status |= stat2
|
||||
self.status |= stat3
|
||||
|
||||
# Get Voltages
|
||||
tmp = self.__read_float(HX.COM_GET_VCC)
|
||||
if tmp is not None:
|
||||
self.vcc = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VIN)
|
||||
if tmp is not None:
|
||||
self.vin = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VDC)
|
||||
if tmp is not None:
|
||||
self.vdc = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VBT)
|
||||
if tmp is not None:
|
||||
self.vbt = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VBA)
|
||||
if tmp is not None:
|
||||
self.vba = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VPF)
|
||||
if tmp is not None:
|
||||
self.vpf = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_VZU)
|
||||
if tmp is not None:
|
||||
self.vzu = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_ABT)
|
||||
if tmp is not None:
|
||||
self.abt = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_ABA)
|
||||
if tmp is not None:
|
||||
self.aba = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_AIN)
|
||||
if tmp is not None:
|
||||
self.ain = tmp
|
||||
|
||||
tmp = self.__read_float(HX.COM_GET_AHX)
|
||||
if tmp is not None:
|
||||
self.ahx = tmp
|
||||
|
||||
self.online = True
|
||||
self.error_count = 0
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
|
||||
# Decode Status
|
||||
if self.status & 0x0100:
|
||||
self.vcc_ok = True
|
||||
else:
|
||||
self.vcc_ok = False
|
||||
|
||||
if self.status & 0x0200:
|
||||
self.vin_ok = True
|
||||
else:
|
||||
self.vin_ok = False
|
||||
|
||||
if self.status & 0x0400:
|
||||
self.vdc_ok = True
|
||||
else:
|
||||
self.vdc_ok = False
|
||||
|
||||
if self.status & 0x0800:
|
||||
self.vbt_ok = True
|
||||
else:
|
||||
self.vbt_ok = False
|
||||
|
||||
if self.status & 0x1000:
|
||||
self.vba_ok = True
|
||||
else:
|
||||
self.vba_ok = False
|
||||
|
||||
if self.status & 0x0010:
|
||||
self.vpf_ok = True
|
||||
else:
|
||||
self.vpf_ok = False
|
||||
|
||||
if self.status & 0x0020:
|
||||
self.vzu_ok = True
|
||||
else:
|
||||
self.vzu_ok = False
|
||||
|
||||
if self.status & 0x2000:
|
||||
self.bt_enabled = True
|
||||
else:
|
||||
self.bt_enabled = False
|
||||
|
||||
if self.status & 0x4000:
|
||||
self.ba_enabled = True
|
||||
else:
|
||||
self.ba_enabled = False
|
||||
|
||||
if self.status & 0x0040:
|
||||
self.mv_enabled = True
|
||||
else:
|
||||
self.mv_enabled = False
|
||||
|
||||
if self.status & 0x0080:
|
||||
self.us_enabled = True
|
||||
else:
|
||||
self.us_enabled = False
|
||||
|
||||
if self.status & 0x8000:
|
||||
self.in_plugged = True
|
||||
else:
|
||||
self.in_plugged = False
|
||||
|
||||
if self.status & 0x0001:
|
||||
self.bt_blocked = True
|
||||
else:
|
||||
self.bt_blocked = False
|
||||
|
||||
if self.status & 0x0002:
|
||||
self.ba_blocked = True
|
||||
else:
|
||||
self.ba_blocked = False
|
||||
|
||||
if self.status & 0x0004:
|
||||
self.bt_full = True
|
||||
else:
|
||||
self.bt_full = False
|
||||
|
||||
if self.status & 0x0008:
|
||||
self.ba_full = True
|
||||
else:
|
||||
self.ba_full = False
|
||||
|
||||
if self.status & 0x010000:
|
||||
self.abt_ok = True
|
||||
else:
|
||||
self.abt_ok = False
|
||||
|
||||
if self.status & 0x020000:
|
||||
self.aba_ok = True
|
||||
else:
|
||||
self.aba_ok = False
|
||||
|
||||
if self.status & 0x040000:
|
||||
self.ain_ok = True
|
||||
else:
|
||||
self.ain_ok = False
|
||||
|
||||
if self.status & 0x080000:
|
||||
self.ahx_ok = True
|
||||
else:
|
||||
self.ahx_ok = False
|
||||
|
||||
# LOW | HIGH
|
||||
if self.vcc < HX.VCC_LOW:
|
||||
self.vcc_low = True
|
||||
else:
|
||||
self.vcc_low = False
|
||||
|
||||
if self.vcc > HX.VCC_HIGH:
|
||||
self.vcc_high = True
|
||||
else:
|
||||
self.vcc_high = False
|
||||
|
||||
if self.vin < HX.VIN_LOW:
|
||||
self.vin_low = True
|
||||
else:
|
||||
self.vin_low = False
|
||||
|
||||
if self.vin > HX.VIN_HIGH:
|
||||
self.vin_high = True
|
||||
else:
|
||||
self.vin_high = False
|
||||
|
||||
if self.vdc < HX.VDC_LOW:
|
||||
self.vdc_low = True
|
||||
else:
|
||||
self.vdc_low = False
|
||||
|
||||
if self.vdc > HX.VDC_HIGH:
|
||||
self.vdc_high = True
|
||||
else:
|
||||
self.vdc_high = False
|
||||
|
||||
if self.vbt < HX.VBT_LOW:
|
||||
self.vbt_low = True
|
||||
else:
|
||||
self.vbt_low = False
|
||||
|
||||
if self.vbt > HX.VBT_FULL:
|
||||
self.vbt_full = True
|
||||
else:
|
||||
self.vbt_full = False
|
||||
|
||||
if self.vba < HX.VBA_LOW:
|
||||
self.vba_low = True
|
||||
else:
|
||||
self.vba_low = False
|
||||
|
||||
if self.vba > HX.VBA_FULL:
|
||||
self.vba_full = True
|
||||
else:
|
||||
self.vba_full = False
|
||||
|
||||
if self.vpf < HX.VPF_LOW:
|
||||
self.vpf_low = True
|
||||
else:
|
||||
self.vpf_low = False
|
||||
|
||||
if self.vpf > HX.VPF_HIGH:
|
||||
self.vpf_high = True
|
||||
else:
|
||||
self.vpf_high = False
|
||||
|
||||
if self.vzu < HX.VZU_LOW:
|
||||
self.vzu_low = True
|
||||
else:
|
||||
self.vzu_low = False
|
||||
|
||||
if self.vzu > HX.VZU_HIGH:
|
||||
self.vzu_high = True
|
||||
else:
|
||||
self.vzu_high = False
|
||||
|
||||
if self.abt < HX.ABT_LOW:
|
||||
self.abt_low = True
|
||||
else:
|
||||
self.abt_low = False
|
||||
|
||||
if self.abt > HX.ABT_HIGH:
|
||||
self.abt_high = True
|
||||
else:
|
||||
self.abt_high = False
|
||||
|
||||
if self.aba < HX.ABA_LOW:
|
||||
self.aba_low = True
|
||||
else:
|
||||
self.aba_low = False
|
||||
|
||||
if self.aba > HX.ABA_HIGH:
|
||||
self.aba_high = True
|
||||
else:
|
||||
self.aba_high = False
|
||||
|
||||
if self.ain < HX.AIN_LOW:
|
||||
self.ain_low = True
|
||||
else:
|
||||
self.ain_low = False
|
||||
|
||||
if self.ain > HX.AIN_HIGH:
|
||||
self.ain_high = True
|
||||
else:
|
||||
self.ain_high = False
|
||||
|
||||
if self.ahx < HX.AHX_LOW:
|
||||
self.ahx_low = True
|
||||
else:
|
||||
self.ahx_low = False
|
||||
|
||||
if self.ahx > HX.AHX_HIGH:
|
||||
self.ahx_high = True
|
||||
else:
|
||||
self.ahx_high = False
|
||||
|
||||
# Too many errors
|
||||
if self.error_count >= HX.POWER_ERROR_LIMIT:
|
||||
self.online = False
|
||||
|
||||
# Unblock PF
|
||||
if (self.mv_enabled and time.clock() - self.__mv_enable_time >=
|
||||
HX.POWER_MV_TIMEOUT / 100):
|
||||
self.mv_blocked = False
|
||||
|
||||
# Delay
|
||||
time.sleep(HX.POWER_DELAY)
|
||||
|
||||
def __sum_check(self, val, sum_):
|
||||
tmp = 0x00
|
||||
for b in val:
|
||||
tmp ^= b
|
||||
tmp ^= HX.XOR_SEQ
|
||||
if tmp == sum_:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __read_float(self, cmd):
|
||||
# Byte array
|
||||
data = array.array('B', [0, 0, 0, 0])
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.POWER_RESPONSE_DELAY)
|
||||
|
||||
# Get bytes
|
||||
data[0] = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
data[1] = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
data[2] = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
data[3] = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
|
||||
# Get check sum
|
||||
sum_ = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
|
||||
# Check and return value
|
||||
if self.__sum_check(data, sum_):
|
||||
return struct.unpack('f', data)[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __read_byte(self, cmd):
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.POWER_RESPONSE_DELAY)
|
||||
|
||||
# Get byte
|
||||
data = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
|
||||
# Get check sum
|
||||
sum_ = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
|
||||
# Check and return value
|
||||
if data ^ HX.XOR_SEQ == sum_:
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
|
||||
def __write_byte(self, cmd):
|
||||
cmd = (cmd << 8) | (cmd ^ HX.XOR_SEQ)
|
||||
self.i2c_bus.write_word_data(HX.POWER_ADDRESS, HX.EXT_COM, cmd)
|
||||
|
||||
def send_cmd(self, cmd):
|
||||
try:
|
||||
with self.lock:
|
||||
# Send command
|
||||
self.__write_byte(cmd)
|
||||
time.sleep(HX.POWER_RESPONSE_DELAY)
|
||||
|
||||
# Get response
|
||||
response = self.i2c_bus.read_byte(HX.POWER_ADDRESS)
|
||||
|
||||
# Return
|
||||
return response
|
||||
except IOError:
|
||||
return HX.IOE_RSP
|
||||
|
||||
def enable_bt(self):
|
||||
# Enable power from BT
|
||||
if not self.bt_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_ENABLE_BT)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already enabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def disable_bt(self):
|
||||
# Disable power from BT
|
||||
if self.bt_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_DISABLE_BT)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already disabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def enable_us(self):
|
||||
# Enable USB power
|
||||
if not self.us_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_ENABLE_US)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already enabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def disable_us(self):
|
||||
# Disable USB power
|
||||
if self.us_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_DISABLE_US)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already disabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def enable_mv(self):
|
||||
# Enable PowerFunctions and servos
|
||||
if not self.mv_enabled:
|
||||
# Save MV enable time
|
||||
self.__mv_enable_time = time.clock()
|
||||
self.mv_blocked = True
|
||||
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_ENABLE_MV)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already enabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def disable_mv(self):
|
||||
# Disable PowerFunctions and servos
|
||||
if self.mv_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_DISABLE_MV)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already disabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def enable_ba(self):
|
||||
# Enable BA
|
||||
if not self.ba_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_ENABLE_BA)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already enabled? OK!
|
||||
return HX.OK_RSP
|
||||
|
||||
def disable_ba(self):
|
||||
# Disable BA
|
||||
if self.ba_enabled:
|
||||
# Run command
|
||||
result = self.send_cmd(HX.COM_DISABLE_BA)
|
||||
|
||||
# Return
|
||||
return result
|
||||
else:
|
||||
# Already disabled? OK!
|
||||
return HX.OK_RSP
|
171
HXbot/HXserver.py
Executable file
171
HXbot/HXserver.py
Executable file
@ -0,0 +1,171 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot server module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import HX
|
||||
import threading
|
||||
import socket
|
||||
import sys
|
||||
import struct
|
||||
|
||||
|
||||
class HXserverClass():
|
||||
|
||||
def __init__(self, hxbot):
|
||||
super(HXserverClass, self).__init__()
|
||||
|
||||
try:
|
||||
self.s = socket.socket(family=socket.AF_INET,
|
||||
type=socket.SOCK_DGRAM)
|
||||
self.s.bind((HX.SRV_HOST, HX.SRV_PORT))
|
||||
self.s.settimeout(HX.SRV_TIMEOUT)
|
||||
except OSError as E:
|
||||
print(E)
|
||||
sys.exit()
|
||||
|
||||
self.hxbot = hxbot
|
||||
|
||||
self.hxpower = None
|
||||
self.reflex = None
|
||||
self.joystick = None
|
||||
self.hxlcd = None
|
||||
self.hxcam = None
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.is_running = False
|
||||
|
||||
def start(self):
|
||||
self.hxpower = self.hxbot.hxpower
|
||||
self.reflex = self.hxbot.reflex
|
||||
self.joystick = self.hxbot.joystick
|
||||
self.hxlcd = self.hxbot.hxlcd
|
||||
self.hxcam = self.hxbot.hxcam
|
||||
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
self.hxpower = None
|
||||
self.reflex = None
|
||||
self.joystick = None
|
||||
self.hxlcd = None
|
||||
self.hxcam = None
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
def __process(self, stopRequest):
|
||||
while not stopRequest.is_set():
|
||||
try:
|
||||
data = self.s.recvfrom(1024)
|
||||
except socket.timeout:
|
||||
continue
|
||||
|
||||
cmd = data[0][0]
|
||||
client = data[1]
|
||||
|
||||
if cmd == HX.SRV_CMD_GET_ALL:
|
||||
self.s.sendto(self.__pack_all(), client)
|
||||
else:
|
||||
pass
|
||||
|
||||
self.s.close()
|
||||
|
||||
def __pack_all(self):
|
||||
# INIT
|
||||
pw = self.hxpower
|
||||
rf = self.reflex
|
||||
lc = self.hxlcd
|
||||
|
||||
ca = self.hxcam
|
||||
if ca is not None:
|
||||
ca_mcam_state = ca.mcam_state
|
||||
ca_rcam_state = ca.rcam_state
|
||||
ca_mmic_state = ca.mmic_state
|
||||
else:
|
||||
ca_mcam_state = 2
|
||||
ca_rcam_state = 2
|
||||
ca_mmic_state = 2
|
||||
|
||||
js = self.joystick
|
||||
if js is not None:
|
||||
js_online = js.online
|
||||
else:
|
||||
js_online = False
|
||||
|
||||
result = struct.pack(
|
||||
'fffffffffff??????????????????????????????????????????????BBB',
|
||||
pw.vcc,
|
||||
pw.vin,
|
||||
pw.vdc,
|
||||
pw.vbt,
|
||||
pw.vba,
|
||||
pw.vpf,
|
||||
pw.vzu,
|
||||
pw.abt,
|
||||
pw.aba,
|
||||
pw.ain,
|
||||
pw.ahx,
|
||||
pw.online,
|
||||
pw.vcc_ok,
|
||||
pw.vin_ok,
|
||||
pw.vdc_ok,
|
||||
pw.vbt_ok,
|
||||
pw.vba_ok,
|
||||
pw.vpf_ok,
|
||||
pw.vzu_ok,
|
||||
pw.abt_ok,
|
||||
pw.aba_ok,
|
||||
pw.ain_ok,
|
||||
pw.ahx_ok,
|
||||
pw.bt_enabled,
|
||||
pw.ba_enabled,
|
||||
pw.bt_blocked,
|
||||
pw.ba_blocked,
|
||||
pw.vcc_low,
|
||||
pw.vcc_high,
|
||||
pw.vin_low,
|
||||
pw.vin_high,
|
||||
pw.vdc_low,
|
||||
pw.vdc_high,
|
||||
pw.vbt_low,
|
||||
pw.vbt_full,
|
||||
pw.vba_low,
|
||||
pw.vba_full,
|
||||
pw.vpf_low,
|
||||
pw.vpf_high,
|
||||
pw.vzu_low,
|
||||
pw.vzu_high,
|
||||
pw.abt_low,
|
||||
pw.abt_high,
|
||||
pw.aba_low,
|
||||
pw.aba_high,
|
||||
pw.ain_low,
|
||||
pw.ain_high,
|
||||
pw.ahx_low,
|
||||
pw.ahx_high,
|
||||
pw.mv_enabled,
|
||||
pw.us_enabled,
|
||||
pw.in_plugged,
|
||||
pw.ba_full,
|
||||
pw.bt_full,
|
||||
rf.online,
|
||||
js_online,
|
||||
lc.online,
|
||||
ca_mcam_state,
|
||||
ca_rcam_state,
|
||||
ca_mmic_state)
|
||||
|
||||
return result
|
1
HXbot/HXsound.py
Executable file
1
HXbot/HXsound.py
Executable file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
224
HXbot/REflex.py
Executable file
224
HXbot/REflex.py
Executable file
@ -0,0 +1,224 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# REflex communication module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import threading
|
||||
import time
|
||||
import HX
|
||||
|
||||
|
||||
class REflexClass():
|
||||
|
||||
def __init__(self, hxbot):
|
||||
self.i2c_bus = hxbot.i2c_bus
|
||||
self.hxbot = hxbot
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
self.lock = hxbot.reflex_lock
|
||||
|
||||
self.joystick = None
|
||||
self.hxpower = None
|
||||
self.control = HX.CONTROL_SRC_DEFAULT
|
||||
|
||||
self.error_count = 0
|
||||
self.online = False
|
||||
self.is_running = False
|
||||
|
||||
self.ready_to_move = False
|
||||
self.last_command_time = 0.0
|
||||
|
||||
self.__move_float = 0
|
||||
self.__steer_center = 0
|
||||
|
||||
# Tuple of commands for execute
|
||||
self.m = (
|
||||
False, # Check
|
||||
HX.MOVE_FLOAT, # Move
|
||||
HX.STEER_CENTER, # Steer
|
||||
HX.HEAD_V_CENTER, # Head vertical orientation
|
||||
HX.HEAD_H_CENTER # Head horizontal orientation
|
||||
)
|
||||
|
||||
# Tuple with results of executions
|
||||
self.s = (
|
||||
HX.NO_RSP,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
|
||||
def start(self):
|
||||
self.joystick = self.hxbot.joystick
|
||||
self.hxpower = self.hxbot.hxpower
|
||||
|
||||
self.__e = threading.Event()
|
||||
self.__t = threading.Thread(target=self.__process, args=(self.__e, ))
|
||||
|
||||
self.__t.start()
|
||||
self.is_running = True
|
||||
|
||||
def stop(self):
|
||||
self.__e.set()
|
||||
self.__t.join()
|
||||
self.is_running = False
|
||||
|
||||
self.__e = None
|
||||
self.__t = None
|
||||
|
||||
self.joystick = None
|
||||
self.hxpower = None
|
||||
|
||||
def start_move(self):
|
||||
result = HX.OK_RSP
|
||||
|
||||
# Enable moving
|
||||
if not self.hxpower.mv_enabled:
|
||||
result = self.hxpower.enable_mv()
|
||||
|
||||
if result != HX.OK_RSP:
|
||||
return
|
||||
|
||||
self.ready_to_move = True
|
||||
|
||||
def stop_move(self, non_block=False):
|
||||
result = HX.OK_RSP
|
||||
|
||||
# Disable moving
|
||||
if self.hxpower.mv_blocked and not non_block:
|
||||
return
|
||||
|
||||
if self.hxpower.mv_enabled:
|
||||
result = self.hxpower.disable_mv()
|
||||
|
||||
if result != HX.OK_RSP:
|
||||
return
|
||||
|
||||
self.ready_to_move = False
|
||||
|
||||
def get_temp(self):
|
||||
return self.__send_command(HX.COM_GET_TEMP)
|
||||
|
||||
def __send_command(self, command):
|
||||
try:
|
||||
with self.lock:
|
||||
self.i2c_bus.write_word_data(HX.REFLEX_ADDRESS, command, 0)
|
||||
time.sleep(HX.REFLEX_RESPONSE_DELAY)
|
||||
response = self.i2c_bus.read_byte(HX.REFLEX_ADDRESS)
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
if self.error_count >= HX.REFLEX_ERROR_LIMIT:
|
||||
self.online = False
|
||||
return HX.IOE_RSP
|
||||
else:
|
||||
self.error_count = 0
|
||||
self.online = True
|
||||
return response
|
||||
|
||||
return HX.NO_RSP
|
||||
|
||||
def __send_ex_command(self, flag, command):
|
||||
try:
|
||||
with self.lock:
|
||||
self.i2c_bus.write_word_data(HX.REFLEX_ADDRESS, HX.EXT_COM,
|
||||
flag << 8 | command)
|
||||
time.sleep(HX.REFLEX_RESPONSE_DELAY)
|
||||
response = self.i2c_bus.read_byte(HX.REFLEX_ADDRESS)
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
if self.error_count >= HX.REFLEX_ERROR_LIMIT:
|
||||
self.online = False
|
||||
return HX.IOE_RSP
|
||||
else:
|
||||
self.error_count = 0
|
||||
self.online = True
|
||||
return response
|
||||
|
||||
return HX.NO_RSP
|
||||
|
||||
def __get_byte(self):
|
||||
try:
|
||||
with self.lock:
|
||||
response = self.i2c_bus.read_byte(HX.REFLEX_ADDRESS)
|
||||
except IOError:
|
||||
if self.online:
|
||||
self.error_count += 1
|
||||
if self.error_count >= HX.REFLEX_ERROR_LIMIT:
|
||||
self.online = False
|
||||
return HX.IOE_RSP
|
||||
else:
|
||||
self.error_count = 0
|
||||
self.online = True
|
||||
return response
|
||||
|
||||
def __process(self, stopRequest):
|
||||
# Process loop
|
||||
while not stopRequest.is_set():
|
||||
# Init cycle
|
||||
have_commands = False
|
||||
|
||||
# Ping REflex
|
||||
self.__send_command(HX.COM_PING)
|
||||
|
||||
# Joystick
|
||||
if self.control == HX.CONTROL_SRC_JOYSTICK and self.joystick:
|
||||
if self.joystick.ready:
|
||||
# Joystick ready! Let's go!
|
||||
if not self.ready_to_move:
|
||||
self.start_move()
|
||||
|
||||
# Get m
|
||||
self.m = self.joystick.get_m()
|
||||
have_commands = self.m[0]
|
||||
else:
|
||||
if self.ready_to_move:
|
||||
self.stop_move(True)
|
||||
time.sleep(0.5)
|
||||
|
||||
# Execute received commands
|
||||
if have_commands:
|
||||
self.s = self.execute(self.m)
|
||||
|
||||
# No commands? Stop move...
|
||||
elif (time.clock() - self.last_command_time >=
|
||||
HX.REFLEX_MOVE_TIMEOUT / 100):
|
||||
self.stop_move()
|
||||
|
||||
def execute(self, m):
|
||||
# Move
|
||||
if m[1] != HX.MOVE_FLOAT:
|
||||
move_rsp = self.__send_ex_command(HX.MOVE_FLAG, m[1])
|
||||
self.__move_float = 0
|
||||
elif self.__move_float < 3:
|
||||
move_rsp = self.__send_ex_command(HX.MOVE_FLAG, m[1])
|
||||
self.__move_float += 1
|
||||
else:
|
||||
move_rsp = HX.OK_RSP
|
||||
|
||||
# Steer
|
||||
if m[2] != HX.STEER_CENTER:
|
||||
steer_rsp = self.__send_ex_command(HX.STEER_FLAG, m[2])
|
||||
self.__steer_center = 0
|
||||
elif self.__steer_center < 3:
|
||||
steer_rsp = self.__send_ex_command(HX.STEER_FLAG, m[2])
|
||||
self.__steer_center += 1
|
||||
else:
|
||||
steer_rsp = HX.OK_RSP
|
||||
|
||||
# Head vertiacal orientation
|
||||
head_v_rsp = self.__send_ex_command(HX.HEAD_V_FLAG, m[3])
|
||||
|
||||
# Head horizontal orientation
|
||||
head_h_rsp = self.__send_ex_command(HX.HEAD_H_FLAG, m[4])
|
||||
|
||||
# Set last command time
|
||||
self.last_command_time = time.clock()
|
||||
|
||||
# Return execution status
|
||||
return (HX.OK_RSP, move_rsp, steer_rsp, head_v_rsp, head_h_rsp)
|
BIN
HXbot/__pycache__/HX.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HX.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HX.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HX.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXcam.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HXcam.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXcontrol.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXcontrol.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXdb.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HXdb.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXjoystick.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXjoystick.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXjoystick.cpython-35.pyc
Executable file
BIN
HXbot/__pycache__/HXjoystick.cpython-35.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXlcd.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HXlcd.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXpower.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXpower.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXpower.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HXpower.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXserver.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXserver.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXserver.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/HXserver.cpython-35.pyc
Normal file
Binary file not shown.
BIN
HXbot/__pycache__/HXu.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXu.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/HXwatchdog.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/HXwatchdog.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/REflex.cpython-34.pyc
Executable file
BIN
HXbot/__pycache__/REflex.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXbot/__pycache__/REflex.cpython-35.pyc
Normal file
BIN
HXbot/__pycache__/REflex.cpython-35.pyc
Normal file
Binary file not shown.
29
HXbot/hxbot.nja
Executable file
29
HXbot/hxbot.nja
Executable file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"mainFile": "HXbot.py",
|
||||
"use-tabs": false,
|
||||
"venv": "",
|
||||
"relatedProjects": [],
|
||||
"name": "HXbot",
|
||||
"license": "GNU General Public License v3",
|
||||
"url": "",
|
||||
"pythonPath": "/usr/bin/python3",
|
||||
"preExecScript": "",
|
||||
"additional_builtins": [],
|
||||
"programParams": "",
|
||||
"indentation": 4,
|
||||
"PYTHONPATH": "",
|
||||
"supported-extensions": [
|
||||
".py",
|
||||
".html",
|
||||
".jpg",
|
||||
".png",
|
||||
".ui",
|
||||
".css",
|
||||
".json",
|
||||
".js",
|
||||
".ini"
|
||||
],
|
||||
"project-type": "Import from sources",
|
||||
"postExecScript": "",
|
||||
"description": "Main program of HXbot"
|
||||
}
|
4
HXcam/audio
Executable file
4
HXcam/audio
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Logitec C920 mic
|
||||
# RTSP
|
||||
cvlc -v 'alsa://hw:0,0' --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}:rtp{sdp=rtsp://:8556/audio}'
|
19
HXcam/mainCam
Executable file
19
HXcam/mainCam
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Logitec C920
|
||||
# 1280x800:30
|
||||
|
||||
# RTSP
|
||||
cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15' --sout '#rtp{sdp=rtsp://:8554/video}' -v --live-caching 50
|
||||
|
||||
# MP4
|
||||
#cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15' --sout '#http{mux=ts,dst=:8080/main.mp4}' -v --live-caching 50
|
||||
|
||||
# OGG
|
||||
#cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15' --sout '#transcode{vcodec=theora}:http{mux=ogg,dst=:8080/main.ogg}' -v --live-caching 50
|
||||
|
||||
# ASF
|
||||
#cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15' --sout '#http{mux=asf,dst=:8080/}' -v --live-caching 50
|
||||
|
||||
#v4l2-ctl --device=/dev/video1 --set-fmt-video=width=1280,height=720,pixelformat=1
|
||||
|
||||
#ffmpeg -r 15 -use_wallclock_as_timestamps 1 -copytb 0 -f v4l2 -vcodec h264 -i /dev/video1 -vcodec copy -f rtsp rtsp://:8554/video
|
5
HXcam/rearCam
Executable file
5
HXcam/rearCam
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# RPI Camera
|
||||
# 1280x800:30
|
||||
# RTSP
|
||||
raspivid -t 0 -n -w 1280 -h 720 -fps 15 -o - | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8555/video}' :demux=h264
|
368
HXgui/HX.py
Executable file
368
HXgui/HX.py
Executable file
@ -0,0 +1,368 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot utility module #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
# I2C bus
|
||||
I2C_BUS_NUMBER = 1
|
||||
EXT_COM = 0xAA
|
||||
XOR_SEQ = 0xFF
|
||||
|
||||
# VAR
|
||||
REFLEX_ADDRESS = 0x04
|
||||
REFLEX_RESPONSE_DELAY = 0.1 # Delay to get response after send command, sec
|
||||
REFLEX_ERROR_LIMIT = 5
|
||||
REFLEX_MOVE_TIMEOUT = 60
|
||||
|
||||
# COMMANDS
|
||||
# Util
|
||||
COM_PING = 0x01
|
||||
COM_GET_TEMP = 0x02
|
||||
COM_GET_DISTANCE = 0x03
|
||||
|
||||
# Stop
|
||||
STOP = 0x0F
|
||||
# Move
|
||||
MOVE_FLAG = 0x04
|
||||
MOVE_FLOAT = 0x10
|
||||
MOVE_FWD1 = 0x11
|
||||
MOVE_FWD2 = 0x12
|
||||
MOVE_FWD3 = 0x13
|
||||
MOVE_FWD4 = 0x14
|
||||
MOVE_FWD5 = 0x15
|
||||
MOVE_FWD6 = 0x16
|
||||
MOVE_FWD7 = 0x17
|
||||
MOVE_BREAK = 0x18
|
||||
MOVE_REV7 = 0x19
|
||||
MOVE_REV6 = 0x1A
|
||||
MOVE_REV5 = 0x1B
|
||||
MOVE_REV4 = 0x1C
|
||||
MOVE_REV3 = 0x1D
|
||||
MOVE_REV2 = 0x1E
|
||||
MOVE_REV1 = 0x1F
|
||||
|
||||
# Steering
|
||||
STEER_FLAG = 0x05
|
||||
STEER_CENTER = 0x20
|
||||
STEER_LEFT1 = 0x21
|
||||
STEER_LEFT2 = 0x22
|
||||
STEER_LEFT3 = 0x23
|
||||
STEER_LEFT4 = 0x24
|
||||
STEER_LEFT5 = 0x25
|
||||
STEER_LEFT6 = 0x26
|
||||
STEER_LEFT7 = 0x27
|
||||
STEER_FIX_CENTER = 0x28
|
||||
STEER_RIGHT7 = 0x29
|
||||
STEER_RIGHT6 = 0x2A
|
||||
STEER_RIGHT5 = 0x2B
|
||||
STEER_RIGHT4 = 0x2C
|
||||
STEER_RIGHT3 = 0x2D
|
||||
STEER_RIGHT2 = 0x2E
|
||||
STEER_RIGHT1 = 0x2F
|
||||
|
||||
# Head
|
||||
HEAD_H_FLAG = 0x30
|
||||
HEAD_V_FLAG = 0x31
|
||||
HEAD_H_R_RANGE = 83
|
||||
HEAD_H_L_RANGE = 94
|
||||
HEAD_V_UP_RANGE = 90
|
||||
HEAD_V_DOWN_RANGE = 25
|
||||
HEAD_H_CENTER = 83
|
||||
HEAD_V_CENTER = 150
|
||||
|
||||
# CONTROL SOURCE
|
||||
CONTROL_SRC_NONE = 0x00
|
||||
CONTROL_SRC_JOYSTICK = 0x01
|
||||
CONTROL_SRC_IRREMOTE = 0x02
|
||||
CONTROL_SRC_SERVER = 0x03
|
||||
CONTROL_SRC_DB = 0x04
|
||||
CONTROL_SRC_SUB1 = 0x11
|
||||
CONTROL_SRC_SUB2 = 0x12
|
||||
CONTROL_SRC_SUB3 = 0x13
|
||||
CONTROL_SRC_SUB4 = 0x14
|
||||
CONTROL_SRC_SUB5 = 0x15
|
||||
|
||||
CONTROL_SRC_DEFAULT = CONTROL_SRC_JOYSTICK
|
||||
|
||||
# MOVE STATES
|
||||
MOVE_STATE_STOP = 0x00
|
||||
MOVE_STATE_MOVE = 0x01
|
||||
|
||||
# STATUS
|
||||
STATUS_INIT = 0x00
|
||||
STATUS_READY = 0x01
|
||||
STATUS_RUNNING = 0x02
|
||||
STATUS_STOP = 0x03
|
||||
STATUS_EXIT = 0x04
|
||||
|
||||
# STATUS STATES
|
||||
#STATUS_STATE_OK = 0x00
|
||||
#STATUS_STATE_WARNING = 0x01
|
||||
#STATUS_STATE_ERROR = 0x02
|
||||
#STATUS_STATE_LOWBAT1 = 0x03
|
||||
#STATUS_STATE_LOWBAT2 = 0x04
|
||||
|
||||
# JOYSTICK
|
||||
JOYSTICK_PATH = '/dev/input/js0'
|
||||
JOYSTICK_READY_TIMEOUT = 60
|
||||
|
||||
# These constants were borrowed from linux/input.h
|
||||
JOYSTICK_AXIS_NAMES = {
|
||||
0x00: 'x',
|
||||
0x01: 'y',
|
||||
0x02: 'z',
|
||||
0x03: 'rx',
|
||||
0x04: 'ry',
|
||||
0x05: 'rz',
|
||||
0x06: 'trottle',
|
||||
0x07: 'rudder',
|
||||
0x08: 'wheel',
|
||||
0x09: 'gas',
|
||||
0x0a: 'brake',
|
||||
0x10: 'hat0x',
|
||||
0x11: 'hat0y',
|
||||
0x12: 'hat1x',
|
||||
0x13: 'hat1y',
|
||||
0x14: 'hat2x',
|
||||
0x15: 'hat2y',
|
||||
0x16: 'hat3x',
|
||||
0x17: 'hat3y',
|
||||
0x18: 'pressure',
|
||||
0x19: 'distance',
|
||||
0x1a: 'tilt_x',
|
||||
0x1b: 'tilt_y',
|
||||
0x1c: 'tool_width',
|
||||
0x20: 'volume',
|
||||
0x28: 'misc',
|
||||
}
|
||||
|
||||
JOYSTICK_BUTTON_NAMES = {
|
||||
0x120: 'trigger',
|
||||
0x121: 'thumb',
|
||||
0x122: 'thumb2',
|
||||
0x123: 'top',
|
||||
0x124: 'top2',
|
||||
0x125: 'pinkie',
|
||||
0x126: 'base',
|
||||
0x127: 'base2',
|
||||
0x128: 'base3',
|
||||
0x129: 'base4',
|
||||
0x12a: 'base5',
|
||||
0x12b: 'base6',
|
||||
0x12f: 'dead',
|
||||
0x130: 'a',
|
||||
0x131: 'b',
|
||||
0x132: 'c',
|
||||
0x133: 'x',
|
||||
0x134: 'y',
|
||||
0x135: 'z',
|
||||
0x136: 'tl',
|
||||
0x137: 'tr',
|
||||
0x138: 'tl2',
|
||||
0x139: 'tr2',
|
||||
0x13a: 'select',
|
||||
0x13b: 'start',
|
||||
0x13c: 'mode',
|
||||
0x13d: 'thumbl',
|
||||
0x13e: 'thumbr',
|
||||
|
||||
0x220: 'dpad_up',
|
||||
0x221: 'dpad_down',
|
||||
0x222: 'dpad_left',
|
||||
0x223: 'dpad_right',
|
||||
|
||||
# XBox 360 controller uses these codes.
|
||||
0x2c0: 'dpad_left',
|
||||
0x2c1: 'dpad_right',
|
||||
0x2c2: 'dpad_up',
|
||||
0x2c3: 'dpad_down',
|
||||
}
|
||||
|
||||
# JOYSTICK BINDS
|
||||
JOYSTICK_MOVE_AXIS = 'y'
|
||||
JOYSTICK_STEER_AXIS = 'x'
|
||||
JOYSTICK_HEAD_V_AXIS = 'rz'
|
||||
JOYSTICK_HEAD_H_AXIS = 'z'
|
||||
JOYSTICK_START_BTN_1 = 'tl2'
|
||||
JOYSTICK_START_BTN_2 = 'tr2'
|
||||
|
||||
# HXpower
|
||||
POWER_ADDRESS = 0x05
|
||||
POWER_RESPONSE_DELAY = 0.05 # Delay to get response after send command, sec
|
||||
POWER_DELAY = 0.3
|
||||
POWER_ERROR_LIMIT = 3
|
||||
POWER_PF_TIMEOUT = 60
|
||||
|
||||
# Commands
|
||||
# VOLTMETERS
|
||||
COM_GET_VIN = 0x01
|
||||
COM_GET_VDC = 0x02
|
||||
COM_GET_VBT = 0x03
|
||||
COM_GET_VBA = 0x04
|
||||
COM_GET_VIS = 0x05
|
||||
COM_GET_VZU = 0x06
|
||||
COM_GET_VCC = 0x07
|
||||
|
||||
# AMPERMETERS
|
||||
COM_GET_AHX = 0x21
|
||||
COM_GET_ABA = 0x22
|
||||
COM_GET_AIN = 0x23
|
||||
COM_GET_ADC = 0x24
|
||||
|
||||
# STATUS
|
||||
COM_GET_STAT1 = 0x08
|
||||
# 0x01 - vcc_ok
|
||||
# 0x02 - vin_ok
|
||||
# 0x04 - vdc_ok
|
||||
# 0x08 - vbt_ok
|
||||
# 0x10 - vba_ok
|
||||
# 0x20 - lr_enabled
|
||||
# 0x40 - ba_enabled
|
||||
# 0x80 - ba_blocked
|
||||
|
||||
COM_GET_STAT2 = 0x09
|
||||
# 0x01 - bl_powered
|
||||
# 0x02 - bl_error
|
||||
# 0x04 - pf_complete
|
||||
# 0x08 - pf_charge
|
||||
# 0x10 - vis_ok
|
||||
# 0x20 - vzu_ok
|
||||
# 0x40 - pf_enabled
|
||||
# 0x80 - bl_enabled
|
||||
|
||||
COM_GET_STAT3 = 0x20
|
||||
# 0x01 - ahx_ok
|
||||
# 0x02 - aba_ok
|
||||
# 0x04 - ain_ok
|
||||
# 0x08 - adc_ok
|
||||
|
||||
# TEMP
|
||||
COM_GET_POWER_TEMP = 0x10
|
||||
|
||||
VIN_MIN = 10.0
|
||||
VIN_MAX = 14.0
|
||||
VIN_LOW = 11.0
|
||||
VIN_HIGH = 13.0
|
||||
|
||||
VDC_MIN = 5.0
|
||||
VDC_MAX = 5.7
|
||||
VDC_LOW = 5.1
|
||||
VDC_HIGH = 5.5
|
||||
|
||||
VBT_MIN = 3.65
|
||||
VBT_MAX = 4.25
|
||||
VBT_LOW = 3.68
|
||||
VBT_FULL = 4.1
|
||||
|
||||
VBA_MIN = 9.0
|
||||
VBA_MAX = 12.8
|
||||
VBA_LOW = 10.0
|
||||
VBA_FULL = 12.4
|
||||
|
||||
VIS_MIN = 4.5
|
||||
VIS_MAX = 5.3
|
||||
VIS_LOW = 4.7
|
||||
VIS_HIGH = 5.2
|
||||
|
||||
VZU_MIN = 5.0
|
||||
VZU_MAX = 6.3
|
||||
VZU_LOW = 5.2
|
||||
VZU_HIGH = 6.2
|
||||
|
||||
VCC_MIN = 4.5
|
||||
VCC_MAX = 5.3
|
||||
VCC_LOW = 4.7
|
||||
VCC_HIGH = 5.1
|
||||
|
||||
AHX_MIN = 0.3
|
||||
AHX_MAX = 2.0
|
||||
AHX_LOW = 0.4
|
||||
AHX_HIGH = 1.2
|
||||
|
||||
ABA_MIN = 0.05
|
||||
ABA_MAX = 2.0
|
||||
ABA_LOW = 0.5
|
||||
ABA_HIGH = 1.5
|
||||
|
||||
AIN_MIN = 0.05
|
||||
AIN_MAX = 2.0
|
||||
AIN_LOW = 0.1
|
||||
AIN_HIGH = 1.5
|
||||
|
||||
ADC_MIN = 0.05
|
||||
ADC_MAX = 3.0
|
||||
ADC_LOW = 0.1
|
||||
ADC_HIGH = 1.5
|
||||
|
||||
# RELAYS
|
||||
COM_POWER_ON_BL = 0x11 # 17
|
||||
COM_POWER_ON_PF = 0x12 # 18
|
||||
COM_SWITCH_TO_IS = 0x13 # 19
|
||||
COM_SWITCH_TO_IN = 0x14 # 20
|
||||
|
||||
COM_SHUTDOWN_BL = 0x15 # 21
|
||||
COM_SHUTDOWN_PF = 0x16 # 22
|
||||
COM_SWITCH_TO_LR = 0x17 # 23
|
||||
COM_SWITCH_TO_BA = 0x18 # 24
|
||||
|
||||
COM_ENABLE_PF = 0x1B # 27
|
||||
COM_DISABLE_PF = 0x1C # 28
|
||||
|
||||
COM_ENABLE_BL = 0x1D # 29
|
||||
COM_DISABLE_BL = 0x1E # 30
|
||||
|
||||
# HXserver
|
||||
SRV_PORT = 50306
|
||||
SRV_HOST = ''
|
||||
SRV_CMD_GET_ALL = 0x01
|
||||
SRV_TIMEOUT = 1
|
||||
SRV_MAX_ERR_COUNT = 3
|
||||
|
||||
# RETURN CODES
|
||||
# Universal return codes
|
||||
OK_RSP = 0x00
|
||||
NO_RSP = 0xFF
|
||||
ERR_RSP = 0x01
|
||||
BLK_RSP = 0x02
|
||||
CSE_RSP = 0x03
|
||||
IOE_RSP = 0x04
|
||||
TMO_RSP = 0x05
|
||||
|
||||
# HXbot modul flags
|
||||
I2C_BUS_ERR = 0x0001
|
||||
HXPOWER_ERR = 0x0002
|
||||
REFLEX_ERR = 0x0004
|
||||
SERVER_ERR = 0x0008
|
||||
|
||||
JOYSTICK_WRN = 0x0010
|
||||
HXCAMERA_WRN = 0x0020
|
||||
HXLCD_WRN = 0x0040
|
||||
HXDB_WRN = 0x0080
|
||||
HXLIGHT_WRN = 0x0100
|
||||
HXSOUND_WRN = 0x0200
|
||||
HXLOG_WRN = 0x0400
|
||||
|
||||
# HXlcd
|
||||
LCD_ADDRESS = 0x06
|
||||
LCD_ERROR_LIMIT = 5
|
||||
LCD_DELAY = 1
|
||||
LCD_RESPONSE_DELAY = 0.05
|
||||
|
||||
# HXcam
|
||||
CAM_MAX_WRN_COUNT = 3
|
||||
CAM_DELAY = 1.0
|
||||
|
||||
CAM_STATE_STP = 0
|
||||
CAM_STATE_RUN = 1
|
||||
CAM_STATE_WRN = 2
|
||||
CAM_STATE_ERR = 3
|
||||
|
||||
# HXdb
|
||||
DB_DELAY = 1.0
|
||||
|
||||
DB_HOST = 'localhost'
|
||||
DB_NAME = 'hxdb'
|
||||
DB_USER = 'hxdb'
|
||||
DB_PASS = 'hxdbP@S$'
|
BIN
HXgui/HX.pyc
Normal file
BIN
HXgui/HX.pyc
Normal file
Binary file not shown.
724
HXgui/HXgui.py
Executable file
724
HXgui/HXgui.py
Executable file
@ -0,0 +1,724 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
########################################
|
||||
# HXbot GUI #
|
||||
# EoF 2016 EoF@itphx.ru #
|
||||
########################################
|
||||
|
||||
import socket
|
||||
import sys
|
||||
import struct
|
||||
import curses
|
||||
import time
|
||||
import HX
|
||||
import select
|
||||
from curses import wrapper
|
||||
|
||||
|
||||
class HXguiClass():
|
||||
|
||||
def __init__(self, stdscr):
|
||||
super(HXguiClass, self).__init__()
|
||||
|
||||
# UDP Socket
|
||||
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.s.settimeout(HX.SRV_TIMEOUT)
|
||||
|
||||
# Init color pairs
|
||||
self.RED_ON_BLACK = 1
|
||||
self.GREEN_ON_BLACK = 2
|
||||
self.YELLOW_ON_BLACK = 3
|
||||
self.BLUE_ON_BLACK = 4
|
||||
self.BLACK_ON_RED = 5
|
||||
curses.init_pair(self.RED_ON_BLACK, curses.COLOR_RED,
|
||||
curses.COLOR_BLACK)
|
||||
curses.init_pair(self.GREEN_ON_BLACK, curses.COLOR_GREEN,
|
||||
curses.COLOR_BLACK)
|
||||
curses.init_pair(self.YELLOW_ON_BLACK, curses.COLOR_YELLOW,
|
||||
curses.COLOR_BLACK)
|
||||
curses.init_pair(self.BLUE_ON_BLACK, curses.COLOR_BLUE,
|
||||
curses.COLOR_BLACK)
|
||||
curses.init_pair(self.BLACK_ON_RED, curses.COLOR_BLACK,
|
||||
curses.COLOR_RED)
|
||||
|
||||
# Params
|
||||
self.power_online = False
|
||||
|
||||
self.vcc = 0.0
|
||||
self.vin = 0.0
|
||||
self.vdc = 0.0
|
||||
self.vbt = 0.0
|
||||
self.vba = 0.0
|
||||
self.vpf = 0.0
|
||||
self.vzu = 0.0
|
||||
self.abt = 0.0
|
||||
self.aba = 0.0
|
||||
self.ain = 0.0
|
||||
self.ahx = 0.0
|
||||
|
||||
self.vcc_ok = False
|
||||
self.vcc_low = False
|
||||
self.vcc_high = False
|
||||
self.vin_ok = False
|
||||
self.vin_low = False
|
||||
self.vin_high = False
|
||||
self.vdc_ok = False
|
||||
self.vdc_low = False
|
||||
self.vdc_high = False
|
||||
self.vbt_ok = False
|
||||
self.vbt_low = False
|
||||
self.vbt_full = False
|
||||
self.vba_ok = False
|
||||
self.vba_low = False
|
||||
self.vba_full = False
|
||||
self.vpf_ok = False
|
||||
self.vpf_low = False
|
||||
self.vpf_high = False
|
||||
self.vzu_ok = False
|
||||
self.vzu_low = False
|
||||
self.vzu_high = False
|
||||
|
||||
self.abt_ok = False
|
||||
self.abt_low = False
|
||||
self.abt_high = False
|
||||
self.aba_ok = False
|
||||
self.aba_low = False
|
||||
self.aba_high = False
|
||||
self.ain_ok = False
|
||||
self.ain_low = False
|
||||
self.ain_high = False
|
||||
self.adc_ok = False
|
||||
self.adc_low = False
|
||||
self.adc_high = False
|
||||
|
||||
self.bt_enabled = False
|
||||
self.ba_enabled = False
|
||||
self.mv_enabled = False
|
||||
self.us_enabled = False
|
||||
|
||||
self.in_plugged = False
|
||||
self.bt_blocked = False
|
||||
self.ba_blocked = False
|
||||
self.bt_full = False
|
||||
self.ba_full = False
|
||||
|
||||
self.reflex_online = False
|
||||
self.joystick_online = False
|
||||
self.lcd_online = False
|
||||
self.main_cam_state = 0
|
||||
self.rear_cam_state = 0
|
||||
self.main_mic_state = 0
|
||||
|
||||
self.error_count = 0
|
||||
self.connected = False
|
||||
|
||||
# Init screen
|
||||
stdscr.clear()
|
||||
stdscr.refresh()
|
||||
|
||||
def draw_interface(self):
|
||||
self.header_text = "-= HXbot console v0.4 =-"
|
||||
self.footer_text = "-= EoF 2016 =-"
|
||||
|
||||
self.header = curses.newwin(1, curses.COLS, 0, 0)
|
||||
self.header.bkgd(' ', curses.A_REVERSE)
|
||||
self.header.addstr(0, (curses.COLS - len(self.header_text)) // 2,
|
||||
self.header_text, curses.A_REVERSE)
|
||||
|
||||
self.footer = curses.newwin(1, curses.COLS, curses.LINES - 1, 0)
|
||||
self.footer.bkgd(' ', curses.A_REVERSE)
|
||||
self.footer.addstr(0, (curses.COLS - len(self.footer_text)) // 2,
|
||||
self.footer_text, curses.A_REVERSE)
|
||||
|
||||
self.comline = curses.newwin(1, curses.COLS, curses.LINES - 2, 0)
|
||||
self.comline.bkgd(' ', curses.A_NORMAL)
|
||||
self.comline.addstr(0, 0, "COMMAND: ", curses.A_BOLD)
|
||||
|
||||
self.mainwin = curses.newwin(curses.LINES - 3, curses.COLS, 1, 0)
|
||||
self.mainwin.border()
|
||||
|
||||
# Draw tables
|
||||
self.mainwin.addstr(2, 3, "| Vcc | Vin | Vdc | Vbt | Vba " +
|
||||
"| Vpf | Vzu |", curses.A_REVERSE)
|
||||
self.mainwin.addstr(3, 3, "| | | | | " +
|
||||
"| | |", curses.A_NORMAL)
|
||||
self.mainwin.addstr(4, 3, "| | | | | " +
|
||||
"| | |", curses.A_NORMAL)
|
||||
|
||||
self.mainwin.addstr(6, 3, "| Abt || Aba || Ain || Ahx |",
|
||||
curses.A_REVERSE)
|
||||
self.mainwin.addstr(7, 3, "| || || || |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(8, 3, "| || || || |",
|
||||
curses.A_NORMAL)
|
||||
|
||||
self.mainwin.addstr(10, 3, "| MAIN POWER || MOVE POWER |",
|
||||
curses.A_REVERSE)
|
||||
self.mainwin.addstr(11, 3, "| || |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(12, 3, "| || |",
|
||||
curses.A_NORMAL)
|
||||
|
||||
#self.mainwin.addstr(11, 41, "| OK |",
|
||||
#curses.A_REVERSE)
|
||||
#self.mainwin.addstr(12, 41, "| |",
|
||||
#curses.A_NORMAL)
|
||||
|
||||
self.mainwin.addstr(2, 55, "| STATUS |",
|
||||
curses.A_REVERSE)
|
||||
self.mainwin.addstr(3, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(4, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(5, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(6, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(7, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(8, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(9, 55, "| |",
|
||||
curses.A_NORMAL)
|
||||
|
||||
self.mainwin.addstr(6, 41, "| BT & BA |",
|
||||
curses.A_REVERSE)
|
||||
self.mainwin.addstr(7, 41, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(8, 41, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(9, 41, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(10, 41, "| |",
|
||||
curses.A_NORMAL)
|
||||
self.mainwin.addstr(11, 41, "| |",
|
||||
curses.A_NORMAL)
|
||||
|
||||
# Add text windows
|
||||
# Voltage states
|
||||
self.vcc_st_win = curses.newwin(1, 5, 4, 5)
|
||||
self.vin_st_win = curses.newwin(1, 5, 4, 12)
|
||||
self.vdc_st_win = curses.newwin(1, 5, 4, 19)
|
||||
self.vbt_st_win = curses.newwin(1, 5, 4, 26)
|
||||
self.vba_st_win = curses.newwin(1, 5, 4, 33)
|
||||
self.vpf_st_win = curses.newwin(1, 5, 4, 40)
|
||||
self.vzu_st_win = curses.newwin(1, 5, 4, 47)
|
||||
|
||||
# Voltage values
|
||||
self.vcc_win = curses.newwin(1, 5, 5, 5)
|
||||
self.vin_win = curses.newwin(1, 5, 5, 12)
|
||||
self.vdc_win = curses.newwin(1, 5, 5, 19)
|
||||
self.vbt_win = curses.newwin(1, 5, 5, 26)
|
||||
self.vba_win = curses.newwin(1, 5, 5, 33)
|
||||
self.vpf_win = curses.newwin(1, 5, 5, 40)
|
||||
self.vzu_win = curses.newwin(1, 5, 5, 47)
|
||||
|
||||
# Current states
|
||||
self.abt_st_win = curses.newwin(1, 6, 8, 5)
|
||||
self.aba_st_win = curses.newwin(1, 6, 8, 14)
|
||||
self.ain_st_win = curses.newwin(1, 6, 8, 23)
|
||||
self.ahx_st_win = curses.newwin(1, 6, 8, 32)
|
||||
|
||||
# Current values
|
||||
self.abt_win = curses.newwin(1, 6, 9, 5)
|
||||
self.aba_win = curses.newwin(1, 6, 9, 14)
|
||||
self.ain_win = curses.newwin(1, 6, 9, 23)
|
||||
self.ahx_win = curses.newwin(1, 6, 9, 32)
|
||||
|
||||
# Status
|
||||
self.bt_st_win = curses.newwin(1, 14, 12, 5)
|
||||
self.ba_st_win = curses.newwin(1, 14, 13, 5)
|
||||
self.mv_st_win = curses.newwin(1, 14, 12, 23)
|
||||
self.us_st_win = curses.newwin(1, 14, 13, 23)
|
||||
|
||||
# Online Status
|
||||
self.pw_online_win = curses.newwin(1, 19, 4, 57)
|
||||
self.rf_online_win = curses.newwin(1, 19, 5, 57)
|
||||
self.js_online_win = curses.newwin(1, 19, 6, 57)
|
||||
self.lc_online_win = curses.newwin(1, 19, 7, 57)
|
||||
self.mc_online_win = curses.newwin(1, 19, 8, 57)
|
||||
self.rc_online_win = curses.newwin(1, 19, 9, 57)
|
||||
self.mm_online_win = curses.newwin(1, 19, 10, 57)
|
||||
|
||||
# BL & BA status
|
||||
self.bt_blocked_win = curses.newwin(1, 9, 8, 43)
|
||||
self.ba_blocked_win = curses.newwin(1, 9, 9, 43)
|
||||
self.in_status_win = curses.newwin(1, 9, 10, 43)
|
||||
self.bt_status_win = curses.newwin(1, 9, 11, 43)
|
||||
self.ba_status_win = curses.newwin(1, 9, 12, 43)
|
||||
|
||||
# Error pad
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.error_pad = curses.newpad(3, 20)
|
||||
self.error_pad.border()
|
||||
self.error_pad.addstr(1, 2, "Connection lost!", clr)
|
||||
|
||||
self.header.refresh()
|
||||
self.footer.refresh()
|
||||
self.mainwin.refresh()
|
||||
|
||||
def draw_data(self):
|
||||
# Set voltage states
|
||||
if self.vcc_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vcc_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vcc_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.vcc_st_win.addstr(0, 0, tst, clr)
|
||||
self.vcc_st_win.refresh()
|
||||
|
||||
if self.vin_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vin_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vin_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.vin_st_win.addstr(0, 0, tst, clr)
|
||||
self.vin_st_win.refresh()
|
||||
|
||||
if self.vdc_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vdc_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vdc_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.vdc_st_win.addstr(0, 0, tst, clr)
|
||||
self.vdc_st_win.refresh()
|
||||
|
||||
if self.vbt_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vbt_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vbt_full:
|
||||
tst = "FULL"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.vbt_st_win.addstr(0, 0, tst, clr)
|
||||
self.vbt_st_win.refresh()
|
||||
|
||||
if self.mv_enabled:
|
||||
if self.vpf_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vpf_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vpf_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
else:
|
||||
tst = "OFF "
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.vpf_st_win.addstr(0, 0, tst, clr)
|
||||
self.vpf_st_win.refresh()
|
||||
|
||||
if self.vba_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vba_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vba_full:
|
||||
tst = "FULL"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.vba_st_win.addstr(0, 0, tst, clr)
|
||||
self.vba_st_win.refresh()
|
||||
|
||||
if self.mv_enabled:
|
||||
if self.vzu_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.vzu_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.vzu_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
else:
|
||||
tst = "OFF "
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.vzu_st_win.addstr(0, 0, tst, clr)
|
||||
self.vzu_st_win.refresh()
|
||||
|
||||
if self.abt_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.abt_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.abt_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.abt_st_win.addstr(0, 0, tst, clr)
|
||||
self.abt_st_win.refresh()
|
||||
|
||||
if self.aba_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.aba_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.aba_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.aba_st_win.addstr(0, 0, tst, clr)
|
||||
self.aba_st_win.refresh()
|
||||
|
||||
if self.ain_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.ain_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.ain_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.ain_st_win.addstr(0, 0, tst, clr)
|
||||
self.ain_st_win.refresh()
|
||||
|
||||
if self.ahx_ok:
|
||||
tst = " OK "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
if self.ahx_low:
|
||||
tst = "LOW "
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
elif self.ahx_high:
|
||||
tst = "HIGH"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
tst = "FAIL"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.ahx_st_win.addstr(0, 0, tst, clr)
|
||||
self.ahx_st_win.refresh()
|
||||
|
||||
# Set voltage values
|
||||
try:
|
||||
self.vcc_win.addstr(0, 0, '{:1.2f}'.format(self.vcc),
|
||||
curses.A_NORMAL)
|
||||
self.vcc_win.refresh()
|
||||
self.vin_win.addstr(0, 0, '{:2.1f}'.format(self.vin),
|
||||
curses.A_NORMAL)
|
||||
self.vin_win.refresh()
|
||||
self.vdc_win.addstr(0, 0, '{:1.2f}'.format(self.vdc),
|
||||
curses.A_NORMAL)
|
||||
self.vdc_win.refresh()
|
||||
self.vbt_win.addstr(0, 0, '{:1.2f}'.format(self.vbt),
|
||||
curses.A_NORMAL)
|
||||
self.vbt_win.refresh()
|
||||
self.vba_win.addstr(0, 0, '{:2.1f}'.format(self.vba),
|
||||
curses.A_NORMAL)
|
||||
self.vba_win.refresh()
|
||||
self.vpf_win.addstr(0, 0, '{:1.2f}'.format(self.vpf),
|
||||
curses.A_NORMAL)
|
||||
self.vpf_win.refresh()
|
||||
self.vzu_win.addstr(0, 0, '{:1.2f}'.format(self.vzu),
|
||||
curses.A_NORMAL)
|
||||
self.vzu_win.refresh()
|
||||
|
||||
self.abt_win.addstr(0, 0, '{:2.2f}'.format(self.abt),
|
||||
curses.A_NORMAL)
|
||||
self.abt_win.refresh()
|
||||
self.aba_win.addstr(0, 0, '{:2.2f}'.format(self.aba),
|
||||
curses.A_NORMAL)
|
||||
self.aba_win.refresh()
|
||||
self.ain_win.addstr(0, 0, '{:2.2f}'.format(self.ain),
|
||||
curses.A_NORMAL)
|
||||
self.ain_win.refresh()
|
||||
self.ahx_win.addstr(0, 0, '{:2.2f}'.format(self.ahx),
|
||||
curses.A_NORMAL)
|
||||
self.ahx_win.refresh()
|
||||
except curses.error:
|
||||
#comline.addstr(0, 0, str(vba), curses.A_NORMAL)
|
||||
#comline.refresh()
|
||||
pass
|
||||
|
||||
# Set status
|
||||
if self.bt_enabled:
|
||||
tst = "BT Enabled "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "BT Disabled"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
self.bt_st_win.addstr(0, 0, tst, clr)
|
||||
self.bt_st_win.refresh()
|
||||
|
||||
if self.ba_enabled:
|
||||
tst = "BA Enabled "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "BA Disabled"
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
self.ba_st_win.addstr(0, 0, tst, clr)
|
||||
self.ba_st_win.refresh()
|
||||
|
||||
if self.mv_enabled:
|
||||
tst = "MV Enabled "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "MV Disabled"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.mv_st_win.addstr(0, 0, tst, clr)
|
||||
self.mv_st_win.refresh()
|
||||
|
||||
if self.us_enabled:
|
||||
tst = "US Enabled "
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "US Disabled"
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.us_st_win.addstr(0, 0, tst, clr)
|
||||
self.us_st_win.refresh()
|
||||
|
||||
# Set online status
|
||||
tst = "HXpower"
|
||||
if self.power_online:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.pw_online_win.addstr(0, 0, tst, clr)
|
||||
self.pw_online_win.refresh()
|
||||
|
||||
tst = "REflex"
|
||||
if self.reflex_online:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.rf_online_win.addstr(0, 0, tst, clr)
|
||||
self.rf_online_win.refresh()
|
||||
|
||||
tst = "Joystick"
|
||||
if self.joystick_online:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.js_online_win.addstr(0, 0, tst, clr)
|
||||
self.js_online_win.refresh()
|
||||
|
||||
tst = "Display"
|
||||
if self.lcd_online:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.lc_online_win.addstr(0, 0, tst, clr)
|
||||
self.lc_online_win.refresh()
|
||||
|
||||
tst = "Main camera"
|
||||
if self.main_cam_state == HX.CAM_STATE_RUN:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
elif self.main_cam_state == HX.CAM_STATE_STP:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
elif self.main_cam_state == HX.CAM_STATE_WRN:
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.mc_online_win.addstr(0, 0, tst, clr)
|
||||
self.mc_online_win.refresh()
|
||||
|
||||
tst = "Rear camera"
|
||||
if self.rear_cam_state == HX.CAM_STATE_RUN:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
elif self.rear_cam_state == HX.CAM_STATE_STP:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
elif self.rear_cam_state == HX.CAM_STATE_WRN:
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.rc_online_win.addstr(0, 0, tst, clr)
|
||||
self.rc_online_win.refresh()
|
||||
|
||||
tst = "Main mic"
|
||||
if self.main_mic_state == HX.CAM_STATE_RUN:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
elif self.main_mic_state == HX.CAM_STATE_STP:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
elif self.main_mic_state == HX.CAM_STATE_WRN:
|
||||
clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.RED_ON_BLACK)
|
||||
self.mm_online_win.addstr(0, 0, tst, clr)
|
||||
self.mm_online_win.refresh()
|
||||
|
||||
# Set EX & BA status
|
||||
tst = "BT block"
|
||||
if self.bt_blocked:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.bt_blocked_win.addstr(0, 0, tst, clr)
|
||||
self.bt_blocked_win.refresh()
|
||||
|
||||
tst = "BA block"
|
||||
if self.ba_blocked:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.ba_blocked_win.addstr(0, 0, tst, clr)
|
||||
self.ba_blocked_win.refresh()
|
||||
|
||||
tst = "IN plugg"
|
||||
if self.in_plugged:
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.in_status_win.addstr(0, 0, tst, clr)
|
||||
self.in_status_win.refresh()
|
||||
|
||||
#if self.bt_charge:
|
||||
#tst = "BT chrg"
|
||||
#clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
if self.bt_full:
|
||||
tst = "BT full"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "BT chrg"
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.bt_status_win.addstr(0, 0, tst, clr)
|
||||
self.bt_status_win.refresh()
|
||||
|
||||
#if self.ba_charge:
|
||||
#tst = "BA chrg"
|
||||
#clr = curses.color_pair(self.YELLOW_ON_BLACK)
|
||||
if self.ba_full:
|
||||
tst = "BA full"
|
||||
clr = curses.color_pair(self.GREEN_ON_BLACK)
|
||||
else:
|
||||
tst = "BA chrg"
|
||||
clr = curses.color_pair(self.BLUE_ON_BLACK)
|
||||
self.ba_status_win.addstr(0, 0, tst, clr)
|
||||
self.ba_status_win.refresh()
|
||||
|
||||
|
||||
def get_data(self):
|
||||
# Get values
|
||||
HOST, PORT = "localhost", HX.SRV_PORT
|
||||
|
||||
self.s.sendto(struct.pack('B', HX.SRV_CMD_GET_ALL), (HOST, PORT))
|
||||
|
||||
try:
|
||||
data = self.s.recv(1024)
|
||||
except socket.timeout:
|
||||
if self.error_count < HX.SRV_MAX_ERR_COUNT:
|
||||
self.error_count += 1
|
||||
else:
|
||||
self.connected = False
|
||||
return
|
||||
|
||||
self.error_count = 0
|
||||
self.connected = True
|
||||
|
||||
self.vcc, self.vin, self.vdc, self.vbt, self.vba, self.vpf, self.vzu, \
|
||||
self.abt, self.aba, self.ain, self.ahx, \
|
||||
self.power_online, \
|
||||
self.vcc_ok, self.vin_ok, self.vdc_ok, self.vbt_ok, self.vba_ok, \
|
||||
self.vpf_ok, self.vzu_ok, \
|
||||
self.abt_ok, self.aba_ok, self.ain_ok, self.ahx_ok, \
|
||||
self.bt_enabled, self.ba_enabled, self.bt_blocked, self.ba_blocked, \
|
||||
self.vcc_low, self.vcc_high, self.vin_low, self.vin_high, \
|
||||
self.vdc_low, self.vdc_high, self.vbt_low, self.vbt_full, \
|
||||
self.vba_low, self.vba_full, self.vpf_low, self.vpf_high, \
|
||||
self.vzu_low, self.vzu_high, \
|
||||
self.abt_low, self.abt_high, self.aba_low, self.aba_high, \
|
||||
self.ain_low, self.ain_high, self.ahx_low, self.ahx_high, \
|
||||
self.mv_enabled, self.us_enabled, self.in_plugged, \
|
||||
self.ba_full, self.bt_full, self.reflex_online, \
|
||||
self.joystick_online, self.lcd_online, \
|
||||
self.main_cam_state, self.rear_cam_state, self.main_mic_state = \
|
||||
struct.unpack(
|
||||
'fffffffffff??????????????????????????????????????????????BBB',
|
||||
data)
|
||||
|
||||
def execute(self):
|
||||
self.draw_interface()
|
||||
redrawed = False
|
||||
|
||||
while True:
|
||||
# Get values
|
||||
self.get_data()
|
||||
|
||||
self.draw_data()
|
||||
|
||||
if not self.connected:
|
||||
self.error_pad.refresh(0, 0, 10, 30, 13, 50)
|
||||
redrawed = False
|
||||
else:
|
||||
if not redrawed:
|
||||
self.mainwin.redrawwin()
|
||||
self.mainwin.refresh()
|
||||
redrawed = True
|
||||
|
||||
self.comline.refresh()
|
||||
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
|
||||
key = self.comline.getkey()
|
||||
if key.upper() == 'Q':
|
||||
break
|
||||
|
||||
time.sleep(0.2)
|
||||
|
||||
|
||||
def main(stdscr):
|
||||
HXgui = HXguiClass(stdscr)
|
||||
HXgui.execute()
|
||||
sys.exit()
|
||||
|
||||
|
||||
# GENERAL PROGRAM
|
||||
if __name__ == "__main__":
|
||||
# Setup
|
||||
stdscr = curses.initscr()
|
||||
curses.start_color()
|
||||
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
stdscr.keypad(True)
|
||||
|
||||
# Start main function
|
||||
wrapper(main)
|
||||
|
||||
# Cleanup
|
||||
curses.nocbreak()
|
||||
stdscr.keypad(False)
|
||||
curses.echo()
|
||||
|
||||
curses.endwin()
|
BIN
HXgui/__pycache__/HX.cpython-34.pyc
Executable file
BIN
HXgui/__pycache__/HX.cpython-34.pyc
Executable file
Binary file not shown.
BIN
HXgui/__pycache__/HX.cpython-35.pyc
Normal file
BIN
HXgui/__pycache__/HX.cpython-35.pyc
Normal file
Binary file not shown.
7
HXgui/hxgui.nja
Executable file
7
HXgui/hxgui.nja
Executable file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"venv": "",
|
||||
"project-type": "Import from sources",
|
||||
"name": "HXgui",
|
||||
"license": "GNU General Public License v3",
|
||||
"description": "HXbot GUI"
|
||||
}
|
339
HXlcd/HXlcd.ino
Normal file
339
HXlcd/HXlcd.ino
Normal file
@ -0,0 +1,339 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot HXlcd firmware /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <Wire.h>
|
||||
#include <TroykaDHT11.h>
|
||||
#include <LiquidCrystal.h>
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 1
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x06
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
#define R_LED 10
|
||||
#define G_LED 9
|
||||
#define B_LED 11
|
||||
#define L_BTN A3
|
||||
#define C_BTN A2
|
||||
#define R_BTN A1
|
||||
#define RED_PIN 10
|
||||
#define GRN_PIN 9
|
||||
#define LCD_BL 3
|
||||
|
||||
// Sensors
|
||||
#define LIGHT A6
|
||||
#define LOUD A7
|
||||
#define TEMP A0
|
||||
#define BUZZ 13
|
||||
#define FREE 12
|
||||
|
||||
#define LED_PIN 13
|
||||
|
||||
#define DELAY1 2000
|
||||
#define DELAY2 500
|
||||
|
||||
// COMMANDS
|
||||
// Util
|
||||
#define COM_PING 0x01
|
||||
#define COM_GET_TEMP 0x02
|
||||
|
||||
// Response
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// VAR
|
||||
LiquidCrystal lcd(2, 4, 5, 6, 7, 8);
|
||||
DHT11 dht(TEMP);
|
||||
|
||||
// эту константу (typVbg) необходимо откалибровать индивидуально
|
||||
const float typVbg = 1.08; // 1.0 -- 1.2
|
||||
|
||||
byte autoresponse = 0;
|
||||
byte cmd = 0;
|
||||
byte flg = 0;
|
||||
byte ext = 0;
|
||||
|
||||
int temp, hum;
|
||||
|
||||
void setup() {
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.println("GO!");
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
// put your setup code here, to run once:
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(RED_PIN, OUTPUT);
|
||||
//digitalWrite(RED_PIN, LOW);
|
||||
pinMode(GRN_PIN, OUTPUT);
|
||||
//digitalWrite(GRN_PIN, LOW);
|
||||
|
||||
pinMode(R_LED, OUTPUT);
|
||||
pinMode(G_LED, OUTPUT);
|
||||
pinMode(B_LED, OUTPUT);
|
||||
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
|
||||
pinMode(L_BTN,INPUT_PULLUP);
|
||||
pinMode(C_BTN,INPUT_PULLUP);
|
||||
pinMode(R_BTN,INPUT_PULLUP);
|
||||
|
||||
pinMode(LIGHT, INPUT);
|
||||
pinMode(LOUD, INPUT);
|
||||
pinMode(FREE, INPUT);
|
||||
pinMode(BUZZ, OUTPUT);
|
||||
|
||||
randomSeed(millis());
|
||||
analogReference(DEFAULT);
|
||||
|
||||
lcd.begin(16, 2);
|
||||
analogWrite(LCD_BL, 255);
|
||||
lcd.print("Hello world!");
|
||||
|
||||
dht.begin();
|
||||
|
||||
delay(2000);
|
||||
lcd.clear();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (digitalRead(FREE) == HIGH) {
|
||||
analogWrite(GRN_PIN, 128);
|
||||
}
|
||||
else {
|
||||
analogWrite(GRN_PIN, 0);
|
||||
}
|
||||
|
||||
displayALL();
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc: ");
|
||||
Serial.println(readvcc());
|
||||
}
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void rgb_control() {
|
||||
//int tmp1;
|
||||
//tmp1 = Read(L_BTN);
|
||||
if (digitalRead(L_BTN) == LOW) {
|
||||
analogWrite(R_LED, 255);
|
||||
//Serial.println(analogRead(L_BTN));
|
||||
}
|
||||
else {
|
||||
analogWrite(R_LED,0);
|
||||
}
|
||||
|
||||
if (digitalRead(C_BTN) == LOW) {
|
||||
analogWrite(G_LED, 255);
|
||||
}
|
||||
else {
|
||||
analogWrite(G_LED,0);
|
||||
}
|
||||
|
||||
if (digitalRead(R_BTN) == LOW) {
|
||||
analogWrite(B_LED, 255);
|
||||
}
|
||||
else {
|
||||
analogWrite(B_LED,0);
|
||||
}
|
||||
}
|
||||
|
||||
void displayTH() {
|
||||
int result;
|
||||
result = dht.read();
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("Temp:");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("Hum:");
|
||||
|
||||
if (result == DHT_OK) {
|
||||
lcd.setCursor(6, 0);
|
||||
lcd.print(dht.getTemperatureC());
|
||||
lcd.print(" C");
|
||||
|
||||
lcd.setCursor(6, 1);
|
||||
lcd.print(dht.getHumidity());
|
||||
lcd.print(" %");
|
||||
}
|
||||
else {
|
||||
lcd.setCursor(6, 0);
|
||||
lcd.print("ERROR");
|
||||
lcd.setCursor(6, 1);
|
||||
lcd.print("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
void displayLL() {
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("Light:");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("Loud:");
|
||||
|
||||
lcd.setCursor(8, 0);
|
||||
lcd.print(analogRead(LIGHT));
|
||||
|
||||
lcd.setCursor(8, 1);
|
||||
lcd.print(analogRead(LOUD));
|
||||
}
|
||||
|
||||
void displayALL() {
|
||||
int result;
|
||||
result = dht.read();
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("Li:");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("Lo:");
|
||||
|
||||
lcd.setCursor(4, 0);
|
||||
lcd.print(analogRead(LIGHT));
|
||||
|
||||
lcd.setCursor(4, 1);
|
||||
lcd.print(analogRead(LOUD));
|
||||
|
||||
lcd.setCursor(9, 0);
|
||||
lcd.print("T:");
|
||||
lcd.setCursor(9, 1);
|
||||
lcd.print("H:");
|
||||
|
||||
if (result == DHT_OK) {
|
||||
lcd.setCursor(11, 0);
|
||||
lcd.print(dht.getTemperatureC());
|
||||
lcd.print("C");
|
||||
|
||||
lcd.setCursor(11, 1);
|
||||
lcd.print(dht.getHumidity());
|
||||
lcd.print(" %");
|
||||
}
|
||||
else {
|
||||
lcd.setCursor(11, 0);
|
||||
lcd.print("ERR");
|
||||
lcd.setCursor(11, 1);
|
||||
lcd.print("ERR");
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
cmd = Wire.read();
|
||||
if (cmd == EXT_COM && byteCount == 3) {
|
||||
flg = 0x00;
|
||||
ext = 0x00;
|
||||
|
||||
if (Wire.available()) ext = Wire.read();
|
||||
if (Wire.available()) flg = Wire.read();
|
||||
}
|
||||
else {
|
||||
// Cleanup I2C bus
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case COM_PING:
|
||||
autoresponse = OK_RSP;
|
||||
blink_red();
|
||||
break;
|
||||
case COM_GET_TEMP:
|
||||
autoresponse = getInternalTemp();
|
||||
break;
|
||||
default:
|
||||
autoresponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for sending data
|
||||
void answer() {
|
||||
Wire.write(autoresponse);
|
||||
}
|
||||
|
||||
void red_on() {
|
||||
digitalWrite(RED_PIN, HIGH);
|
||||
}
|
||||
|
||||
void red_off() {
|
||||
digitalWrite(RED_PIN, LOW);
|
||||
}
|
||||
|
||||
void blink_red() {
|
||||
red_on();
|
||||
delay(100);
|
||||
red_off();
|
||||
}
|
||||
|
||||
// Get the internal temperature of the arduino
|
||||
double getInternalTemp(void) {
|
||||
unsigned int wADC;
|
||||
double t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return (t);
|
||||
}
|
||||
|
||||
float readvcc() {
|
||||
byte i;
|
||||
float tmp = 0.0;
|
||||
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
16
HXlcd2/HXlcd2.h
Normal file
16
HXlcd2/HXlcd2.h
Normal file
@ -0,0 +1,16 @@
|
||||
#define WHITE 0xFFFF
|
||||
#define BLACK 0x0000
|
||||
#define GRAY 0x7BEF
|
||||
#define DGRAY 0x2124
|
||||
#define BLUE 0x051C
|
||||
#define LBLUE 0x96BC
|
||||
#define DBLUE 0x0311
|
||||
#define YELLOW 0xFF60
|
||||
#define LYELLOW 0xFFAD
|
||||
#define DYELLOW 0xBD80
|
||||
|
||||
#define SCR_MAX 5
|
||||
#define SCR1_MAX 5
|
||||
|
||||
#define BTN_TIMEOUT 500
|
||||
|
690
HXlcd2/HXlcd2.ino
Normal file
690
HXlcd2/HXlcd2.ino
Normal file
@ -0,0 +1,690 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot HXlcd firmware /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <Wire.h>
|
||||
#include <TroykaDHT11.h>
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_ST7735.h> // Hardware-specific library
|
||||
#include <SPI.h>
|
||||
#include "HXlcd2.h"
|
||||
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 1
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x06
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
#define R_LED 10
|
||||
#define G_LED 9
|
||||
#define B_LED 11
|
||||
#define L_BTN A3
|
||||
#define C_BTN A2
|
||||
#define R_BTN A1
|
||||
|
||||
//clk 4, din 5, dc 6, cs 7, rst 8
|
||||
#define TFT_BL 3
|
||||
#define TFT_SCLK 4
|
||||
#define TFT_MOSI 5
|
||||
#define TFT_DC 6
|
||||
#define TFT_CS 7
|
||||
#define TFT_RST 8
|
||||
|
||||
// Sensors
|
||||
#define LIGHT A6
|
||||
#define LOUD A7
|
||||
#define TEMP A0
|
||||
#define BUZZ 13
|
||||
#define FREE 12
|
||||
|
||||
#define LED_PIN 13
|
||||
|
||||
#define DELAY1 2000
|
||||
#define DELAY2 500
|
||||
|
||||
// COMMANDS
|
||||
// Util
|
||||
#define COM_PING 0x01
|
||||
#define COM_GET_TEMP 0x02
|
||||
|
||||
// Response
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// VAR
|
||||
|
||||
DHT11 dht(TEMP);
|
||||
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
|
||||
|
||||
// эту константу (typVbg) необходимо откалибровать индивидуально
|
||||
const float typVbg = 1.08; // 1.0 -- 1.2
|
||||
|
||||
byte autoresponse = 0;
|
||||
byte cmd = 0;
|
||||
byte flg = 0;
|
||||
byte ext = 0;
|
||||
|
||||
int temp, hum;
|
||||
|
||||
float p = 3.1415926;
|
||||
float vcc;
|
||||
bool l_pressed = false, c_pressed = false, r_pressed = false;
|
||||
bool menu_drawed = false;
|
||||
byte screen = 0, line = 1;
|
||||
|
||||
unsigned long t;
|
||||
|
||||
void setup() {
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.begin(9600);
|
||||
Serial.println("GO!");
|
||||
}
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
// put your setup code here, to run once:
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
pinMode(R_LED, OUTPUT);
|
||||
pinMode(G_LED, OUTPUT);
|
||||
pinMode(B_LED, OUTPUT);
|
||||
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
|
||||
pinMode(L_BTN, INPUT_PULLUP);
|
||||
pinMode(C_BTN, INPUT_PULLUP);
|
||||
pinMode(R_BTN, INPUT_PULLUP);
|
||||
|
||||
pinMode(LIGHT, INPUT);
|
||||
pinMode(LOUD, INPUT);
|
||||
pinMode(FREE, INPUT);
|
||||
pinMode(BUZZ, OUTPUT);
|
||||
|
||||
randomSeed(millis());
|
||||
analogReference(DEFAULT);
|
||||
|
||||
// Use this initializer if you're using a 1.8" TFT
|
||||
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
|
||||
tft.fillScreen(ST7735_BLACK);
|
||||
|
||||
tft.drawRect(0, 0, 128, 160, ST7735_GREEN);
|
||||
tft.drawRect(1, 1, 126, 158, ST7735_WHITE);
|
||||
drawL();
|
||||
drawC();
|
||||
drawR();
|
||||
analogWrite(TFT_BL, 255);
|
||||
|
||||
dht.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (digitalRead(FREE) == HIGH) {
|
||||
analogWrite(G_LED, 128);
|
||||
}
|
||||
else {
|
||||
analogWrite(G_LED, 0);
|
||||
}
|
||||
|
||||
// if (DEBUG) {
|
||||
// Serial.println(r_pressed);
|
||||
// Serial.println(c_pressed);
|
||||
// Serial.println(l_pressed);
|
||||
// }
|
||||
|
||||
readButtons();
|
||||
drawMenu();
|
||||
//displayALL();
|
||||
}
|
||||
|
||||
void drawMenu() {
|
||||
|
||||
if (millis() - t < BTN_TIMEOUT) return;
|
||||
|
||||
if (screen == 0) {
|
||||
if (l_pressed) {
|
||||
line++;
|
||||
if (line > SCR1_MAX) line = 1;
|
||||
drawPointer();
|
||||
t = millis();
|
||||
}
|
||||
if (r_pressed) {
|
||||
line--;
|
||||
if (line < 1) line = SCR1_MAX;
|
||||
drawPointer();
|
||||
t = millis();
|
||||
}
|
||||
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 8);
|
||||
tft.print("MAIN");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(20, 20);
|
||||
tft.print("HXbot");
|
||||
tft.setCursor(20, 30);
|
||||
tft.print("REflex");
|
||||
tft.setCursor(20, 40);
|
||||
tft.print("HXpower");
|
||||
tft.setCursor(20, 50);
|
||||
tft.print("HXlcd");
|
||||
tft.setCursor(20, 60);
|
||||
tft.print("HXcamera");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = line;
|
||||
line = 0;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (screen == 1) {
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(49, 8);
|
||||
tft.print("HXbot");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 130);
|
||||
tft.print("back");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = 0;
|
||||
line = 1;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (screen == 2) {
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(49, 8);
|
||||
tft.print("REflex");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 130);
|
||||
tft.print("back");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = 0;
|
||||
line = 1;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (screen == 3) {
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(49, 8);
|
||||
tft.print("HXpower");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 130);
|
||||
tft.print("back");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = 0;
|
||||
line = 1;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (screen == 4) {
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(49, 8);
|
||||
tft.print("HXlcd");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 130);
|
||||
tft.print("back");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = 0;
|
||||
line = 1;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (screen == 5) {
|
||||
if (! menu_drawed) {
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(49, 8);
|
||||
tft.print("HXcamera");
|
||||
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(52, 130);
|
||||
tft.print("back");
|
||||
|
||||
drawPointer();
|
||||
|
||||
menu_drawed = true;
|
||||
}
|
||||
|
||||
if (c_pressed) {
|
||||
screen = 0;
|
||||
line = 1;
|
||||
clearMenu();
|
||||
t = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void clearMenu() {
|
||||
tft.fillRect(2, 2, 123, 140, BLACK);
|
||||
menu_drawed = false;
|
||||
}
|
||||
|
||||
void drawPointer() {
|
||||
byte x1, y1, x2, y2, x3, y3;
|
||||
|
||||
if (line != 0) {
|
||||
x1 = 10;
|
||||
y1 = 11 + line * 10;
|
||||
x2 = 10;
|
||||
y2 = 15 + line * 10;
|
||||
x3 = 15;
|
||||
y3 = 13 + line * 10;
|
||||
}
|
||||
else {
|
||||
x1 = 42;
|
||||
y1 = 131;
|
||||
x2 = 42;
|
||||
y2 = 135;
|
||||
x3 = 47;
|
||||
y3 = 133;
|
||||
}
|
||||
|
||||
tft.fillRect(10, 20, 6, 100, BLACK);
|
||||
tft.fillTriangle(x1, y1, x2, y2, x3, y3, WHITE);
|
||||
}
|
||||
|
||||
void displayALL() {
|
||||
// Vcc
|
||||
vcc = readvcc();
|
||||
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print("Vcc=");
|
||||
if (vcc < 4.8 || vcc > 5.2)
|
||||
tft.setTextColor(ST7735_RED, ST7735_BLACK);
|
||||
else
|
||||
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
|
||||
|
||||
tft.print(vcc);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print(" V ");
|
||||
|
||||
// Light
|
||||
tft.setCursor(10, 20);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print("Lightness=");
|
||||
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
|
||||
tft.print(analogRead(LIGHT));
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print(" UE ");
|
||||
|
||||
// Loud
|
||||
tft.setCursor(10, 30);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print("Loud=");
|
||||
tft.setTextColor(ST7735_MAGENTA, ST7735_BLACK);
|
||||
tft.print(analogRead(LOUD));
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print(" UE ");
|
||||
|
||||
// TH
|
||||
int result;
|
||||
result = dht.read();
|
||||
|
||||
tft.setCursor(10, 40);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print("Temp=");
|
||||
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
|
||||
if (result == DHT_OK) tft.print(dht.getTemperatureC()); else tft.print("ERR");
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print(" C ");
|
||||
|
||||
tft.setCursor(10, 50);
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print("Hum=");
|
||||
tft.setTextColor(ST7735_BLUE, ST7735_BLACK);
|
||||
if (result == DHT_OK) tft.print(dht.getHumidity()); else tft.print("ERR");
|
||||
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||
tft.print(" % ");
|
||||
}
|
||||
|
||||
void readButtons() {
|
||||
if ((digitalRead(L_BTN) == LOW) && ! l_pressed) {
|
||||
l_pressed = true;
|
||||
drawL();
|
||||
}
|
||||
else {
|
||||
if ((digitalRead(L_BTN) == HIGH) && l_pressed) {
|
||||
l_pressed = false;
|
||||
drawL();
|
||||
}
|
||||
}
|
||||
|
||||
if ((digitalRead(C_BTN) == LOW) && ! c_pressed) {
|
||||
c_pressed = true;
|
||||
drawC();
|
||||
}
|
||||
else {
|
||||
if ((digitalRead(C_BTN) == HIGH) && c_pressed) {
|
||||
c_pressed = false;
|
||||
drawC();
|
||||
}
|
||||
}
|
||||
|
||||
if ((digitalRead(R_BTN) == LOW) && ! r_pressed) {
|
||||
r_pressed = true;
|
||||
drawR();
|
||||
}
|
||||
else {
|
||||
if ((digitalRead(R_BTN) == HIGH) && r_pressed) {
|
||||
r_pressed = false;
|
||||
drawR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawL() {
|
||||
tft.fillRoundRect(4, 145, 37, 12, 3, YELLOW);
|
||||
if (! l_pressed) {
|
||||
tft.drawRoundRect(4, 145, 37, 12, 3, LYELLOW);
|
||||
tft.drawLine(6, 156, 38, 156, DYELLOW);
|
||||
tft.drawLine(40, 147, 40, 154, DYELLOW);
|
||||
tft.drawPixel(5, 155, DYELLOW);
|
||||
tft.drawPixel(39, 155, DYELLOW);
|
||||
tft.fillTriangle(15, 147, 29, 147, 22, 154, GRAY);
|
||||
tft.drawTriangle(15, 147, 29, 147, 22, 154, DGRAY);
|
||||
}
|
||||
else {
|
||||
tft.drawRoundRect(4, 145, 37, 12, 3, DYELLOW);
|
||||
tft.drawLine(6, 156, 38, 156, LYELLOW);
|
||||
tft.drawLine(40, 147, 40, 154, LYELLOW);
|
||||
tft.drawPixel(5, 155, LYELLOW);
|
||||
tft.drawPixel(39, 155, LYELLOW);
|
||||
tft.fillTriangle(15, 147, 29, 147, 22, 154, WHITE);
|
||||
tft.drawTriangle(15, 147, 29, 147, 22, 154, DGRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void drawC() {
|
||||
tft.fillRoundRect(44, 144, 40, 12, 3, BLUE);
|
||||
if (! c_pressed) {
|
||||
tft.drawRoundRect(44, 144, 40, 12, 3, LBLUE);
|
||||
tft.drawLine(46, 155, 81, 155, DBLUE);
|
||||
tft.drawLine(83, 146, 83, 153, DBLUE);
|
||||
tft.drawPixel(45, 154, DBLUE);
|
||||
tft.drawPixel(82, 154, DBLUE);
|
||||
tft.fillRoundRect(60, 146, 8, 8, 3, GRAY);
|
||||
tft.drawRoundRect(60, 146, 8, 8, 3, DGRAY);
|
||||
}
|
||||
else {
|
||||
tft.drawRoundRect(44, 144, 40, 12, 3, DBLUE);
|
||||
tft.drawLine(46, 155, 81, 155, LBLUE);
|
||||
tft.drawLine(83, 146, 83, 153, LBLUE);
|
||||
tft.drawPixel(45, 154, LBLUE);
|
||||
tft.drawPixel(82, 154, LBLUE);
|
||||
tft.fillRoundRect(60, 146, 8, 8, 3, WHITE);
|
||||
tft.drawRoundRect(60, 146, 8, 8, 3, DGRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void drawR() {
|
||||
tft.fillRoundRect(86, 145, 37, 12, 3, YELLOW);
|
||||
if (! r_pressed) {
|
||||
tft.drawRoundRect(86, 145, 37, 12, 3, LYELLOW);
|
||||
tft.drawLine(88, 156, 120, 156, DYELLOW);
|
||||
tft.drawLine(122, 147, 122, 154, DYELLOW);
|
||||
tft.drawPixel(87, 155, DYELLOW);
|
||||
tft.drawPixel(121, 155, DYELLOW);
|
||||
tft.fillTriangle(97, 154, 111, 154, 104, 147, GRAY);
|
||||
tft.drawTriangle(97, 154, 111, 154, 104, 147, DGRAY);
|
||||
}
|
||||
else {
|
||||
tft.drawRoundRect(86, 145, 37, 12, 3, DYELLOW);
|
||||
tft.drawLine(88, 156, 120, 156, LYELLOW);
|
||||
tft.drawLine(122, 147, 122, 154, LYELLOW);
|
||||
tft.drawPixel(87, 155, LYELLOW);
|
||||
tft.drawPixel(121, 155, LYELLOW);
|
||||
tft.fillTriangle(97, 154, 111, 154, 104, 147, WHITE);
|
||||
tft.drawTriangle(97, 154, 111, 154, 104, 147, DGRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_control() {
|
||||
//int tmp1;
|
||||
//tmp1 = Read(L_BTN);
|
||||
if (digitalRead(L_BTN) == LOW) {
|
||||
analogWrite(R_LED, 255);
|
||||
//Serial.println(analogRead(L_BTN));
|
||||
}
|
||||
else {
|
||||
analogWrite(R_LED,0);
|
||||
}
|
||||
|
||||
if (digitalRead(C_BTN) == LOW) {
|
||||
analogWrite(G_LED, 255);
|
||||
}
|
||||
else {
|
||||
analogWrite(G_LED,0);
|
||||
}
|
||||
|
||||
if (digitalRead(R_BTN) == LOW) {
|
||||
analogWrite(B_LED, 255);
|
||||
}
|
||||
else {
|
||||
analogWrite(B_LED,0);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
cmd = Wire.read();
|
||||
if (cmd == EXT_COM && byteCount == 3) {
|
||||
flg = 0x00;
|
||||
ext = 0x00;
|
||||
|
||||
if (Wire.available()) ext = Wire.read();
|
||||
if (Wire.available()) flg = Wire.read();
|
||||
}
|
||||
else {
|
||||
// Cleanup I2C bus
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case COM_PING:
|
||||
autoresponse = OK_RSP;
|
||||
blink_red();
|
||||
break;
|
||||
case COM_GET_TEMP:
|
||||
autoresponse = getInternalTemp();
|
||||
break;
|
||||
default:
|
||||
autoresponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for sending data
|
||||
void answer() {
|
||||
Wire.write(autoresponse);
|
||||
}
|
||||
|
||||
void blink_red() {
|
||||
digitalWrite(R_LED, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(R_LED, LOW);
|
||||
}
|
||||
|
||||
// Get the internal temperature of the arduino
|
||||
double getInternalTemp(void) {
|
||||
unsigned int wADC;
|
||||
double t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return (t);
|
||||
}
|
||||
|
||||
float readvcc() {
|
||||
float tmp = 0.0;
|
||||
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void tftPrintTest() {
|
||||
tft.setTextWrap(false);
|
||||
tft.fillScreen(ST7735_GREEN);
|
||||
tft.setCursor(0, 30);
|
||||
tft.setTextColor(ST7735_RED);
|
||||
tft.setTextSize(1);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(ST7735_YELLOW);
|
||||
tft.setTextSize(2);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(ST7735_GREEN);
|
||||
tft.setTextSize(3);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(ST7735_BLUE);
|
||||
tft.setTextSize(4);
|
||||
tft.print(1234.567);
|
||||
delay(1500);
|
||||
tft.setCursor(0, 0);
|
||||
tft.fillScreen(ST7735_BLACK);
|
||||
tft.setTextColor(ST7735_WHITE);
|
||||
tft.setTextSize(0);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextSize(1);
|
||||
tft.setTextColor(ST7735_GREEN);
|
||||
tft.print(p, 6);
|
||||
tft.println(" Want pi?");
|
||||
tft.println(" ");
|
||||
tft.print(8675309, HEX); // print 8,675,309 out in HEX!
|
||||
tft.println(" Print HEX!");
|
||||
tft.println(" ");
|
||||
tft.setTextColor(ST7735_WHITE);
|
||||
tft.println("Sketch has been");
|
||||
tft.println("running for: ");
|
||||
tft.setTextColor(ST7735_MAGENTA);
|
||||
tft.print(millis() / 1000);
|
||||
tft.setTextColor(ST7735_WHITE);
|
||||
tft.print(" seconds.");
|
||||
}
|
||||
|
||||
void tftTest() {
|
||||
//
|
||||
tft.fillScreen(ST7735_BLACK);
|
||||
tft.drawRect(0, 0, 128, 160, ST7735_GREEN);
|
||||
tft.drawRect(1, 1, 126, 158, ST7735_WHITE);
|
||||
|
||||
// Smile
|
||||
tft.fillCircle(64, 80, 40, ST7735_YELLOW);
|
||||
//tft.drawCircle(64, 80, 40, ST7735_BLUE);
|
||||
|
||||
tft.fillRoundRect(45, 63, 10, 15, 3, ST7735_BLACK);
|
||||
tft.fillRoundRect(73, 63, 10, 15, 3, ST7735_BLACK);
|
||||
|
||||
tft.fillTriangle(50, 95, 78, 95, 70, 105, ST7735_BLACK);
|
||||
|
||||
tft.setCursor(33, 132);
|
||||
tft.setTextColor(ST7735_YELLOW);
|
||||
tft.setTextSize(2);
|
||||
tft.print("HELLO!");
|
||||
|
||||
// for (byte i = 1; i <= 31; i++) {
|
||||
// tft.drawRect(i * 2, i * 3, 128 - i * 4, 160 - i * 5, ST7735_WHITE);
|
||||
// delay(100);
|
||||
// //tft.drawRect(i * 2, i * 2, 128 - i * 4, 160 - i * 4, ST7735_BLACK);
|
||||
// }
|
||||
}
|
||||
|
824
HXpower/HXpower.ino
Executable file
824
HXpower/HXpower.ino
Executable file
@ -0,0 +1,824 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot HXpower firmware /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 0
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x05
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
#define VIN_PIN 0
|
||||
#define VDC_PIN 1
|
||||
#define VBT_PIN 2
|
||||
#define VBA_PIN 3
|
||||
|
||||
#define R_BL 7
|
||||
#define R_PF 6
|
||||
#define R_HX 5
|
||||
#define R_IS 4
|
||||
#define BL_RED_PIN 8
|
||||
#define BL_GRN_PIN 9
|
||||
#define BTN_PIN 2
|
||||
#define LED_PIN 3
|
||||
|
||||
#define REP_COUNT 5
|
||||
|
||||
#define TIMEOUT 5000
|
||||
|
||||
// COMMANDS
|
||||
// VOLTMETERS
|
||||
#define COM_GET_VIN 0x01
|
||||
#define COM_GET_VDC 0x02
|
||||
#define COM_GET_VBT 0x03
|
||||
#define COM_GET_VBA 0x04
|
||||
#define COM_GET_VCC 0x07
|
||||
|
||||
// TEMP
|
||||
#define COM_GET_TEMP 0x06
|
||||
|
||||
// STATUS
|
||||
#define COM_GET_STAT1 0x08
|
||||
#define COM_GET_STAT2 0x09
|
||||
|
||||
// RELAYS
|
||||
#define COM_POWER_ON_BL 0x11 // 17
|
||||
#define COM_POWER_ON_PF 0x12 // 18
|
||||
#define COM_SWITCH_TO_IS 0x13 // 19
|
||||
#define COM_SWITCH_TO_IN 0x14 // 20
|
||||
|
||||
#define COM_SHUTDOWN_BL 0x15 // 21
|
||||
#define COM_SHUTDOWN_PF 0x16 // 22
|
||||
#define COM_SWITCH_TO_LR 0x17 // 23
|
||||
#define COM_SWITCH_TO_BA 0x18 // 24
|
||||
|
||||
#define COM_ENABLE_PF 0x1B // 27
|
||||
#define COM_DISABLE_PF 0x1C // 28
|
||||
|
||||
#define COM_ENABLE_BL 0x1D // 29
|
||||
#define COM_DISABLE_BL 0x1E // 30
|
||||
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// CONST
|
||||
#define DELAY_TIME 900
|
||||
#define BA_TIMEOUT 3000
|
||||
#define BA_BLOCK_TIMEOUT 30000
|
||||
#define BUTTON_CYCLES 4
|
||||
#define V_CHECK_CYCLES 3
|
||||
|
||||
#define VIN_MIN 10.0
|
||||
#define VIN_MAX 14.0
|
||||
|
||||
#define VDC_MIN 4.8
|
||||
#define VDC_MAX 6.0
|
||||
|
||||
#define VBT_MIN 3.0
|
||||
#define VBT_MAX 4.25
|
||||
|
||||
#define VBA_MIN 6.0
|
||||
#define VBA_MAX 8.4
|
||||
|
||||
#define VCC_MIN 4.5
|
||||
#define VCC_MAX 5.3
|
||||
|
||||
// VAR
|
||||
// резисторы делителя напряжения
|
||||
const float r1_1 = 200000; // 200K
|
||||
const float r1_2 = 100000; // 100K
|
||||
const float r2_1 = 100000; // 100K
|
||||
const float r2_2 = 100000; // 100K
|
||||
const float r3_1 = 100000; // 100K
|
||||
const float r3_2 = 100000; // 100K
|
||||
const float r4_1 = 200000; // 200K
|
||||
const float r4_2 = 100000; // 100K
|
||||
|
||||
// эту константу (typVbg) необходимо откалибровать индивидуально
|
||||
const float typVbg = 1.083; // 1.0 -- 1.2
|
||||
|
||||
float vcc = 0.0;
|
||||
float Vmax1, Vmax2, Vmax3, Vmax4;
|
||||
float kin, kdc, kbt, kba;
|
||||
float vin, vdc, vbt, vba;
|
||||
float tin, tdc, tbt, tba;
|
||||
|
||||
//char *stime;
|
||||
|
||||
byte cmd = 0x00;
|
||||
byte ext = 0x00;
|
||||
byte sum = 0x00;
|
||||
|
||||
unsigned long lastCommandTime = 0;
|
||||
byte autoResponse = 0x00;
|
||||
|
||||
byte byteResponse = 0x00;
|
||||
boolean needByte = false;
|
||||
boolean needSumm = false;
|
||||
|
||||
float floatResponse = 0.0;
|
||||
boolean needFloat = false;
|
||||
byte floatByte = 0;
|
||||
|
||||
byte ba_count = 0;
|
||||
unsigned long ba_time;
|
||||
boolean ba_blocked = false;
|
||||
byte button_count = 0;
|
||||
|
||||
boolean vin_ok = false;
|
||||
byte vin_count = 0;
|
||||
|
||||
boolean vdc_ok = false;
|
||||
byte vdc_count = 0;
|
||||
|
||||
boolean vbt_ok = false;
|
||||
byte vbt_count = 0;
|
||||
|
||||
boolean vba_ok = false;
|
||||
byte vba_count = 0;
|
||||
|
||||
boolean vcc_ok = false;
|
||||
byte vcc_count = 0;
|
||||
|
||||
boolean ba_enabled = true;
|
||||
boolean lr_enabled = true;
|
||||
boolean pf_enabled = false;
|
||||
boolean bl_enabled = false;
|
||||
|
||||
boolean bl_powered = false;
|
||||
boolean bl_error = false;
|
||||
boolean ba_full = false;
|
||||
boolean ba_charge = false;
|
||||
|
||||
byte status_1 = 0x00;
|
||||
byte status_2 = 0x00;
|
||||
|
||||
// Loop delay
|
||||
int delay_time = DELAY_TIME;
|
||||
|
||||
/****************************************************************************
|
||||
* Главная программа
|
||||
****************************************************************************/
|
||||
|
||||
void setup() {
|
||||
if (DEBUG) {
|
||||
Serial.begin(9600);
|
||||
Serial.println("---");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// определение опорного напряжения
|
||||
analogReference(DEFAULT); // DEFAULT INTERNAL использовать vcc как AREF
|
||||
delay(100);
|
||||
|
||||
kin = r1_2 / (r1_1 + r1_2);
|
||||
kdc = r2_2 / (r2_1 + r2_2);
|
||||
kbt = r3_2 / (r3_1 + r3_2);
|
||||
kba = r4_2 / (r4_1 + r4_2);
|
||||
|
||||
vcc = readvcc();
|
||||
Vmax1 = vcc / kin;
|
||||
Vmax2 = vcc / kdc;
|
||||
Vmax3 = vcc / kbt;
|
||||
Vmax4 = vcc / kba;
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc= ");
|
||||
Serial.println(vcc);
|
||||
Serial.print("Vmax1= ");
|
||||
Serial.println(Vmax1);
|
||||
Serial.print("Vmax2= ");
|
||||
Serial.println(Vmax2);
|
||||
Serial.print("Vmax3= ");
|
||||
Serial.println(Vmax3);
|
||||
Serial.print("Vmax4= ");
|
||||
Serial.println(Vmax4);
|
||||
Serial.println("---");
|
||||
}
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
pinMode(R_BL, OUTPUT);
|
||||
pinMode(R_PF, OUTPUT);
|
||||
pinMode(R_HX, OUTPUT);
|
||||
pinMode(R_IS, OUTPUT);
|
||||
pinMode(BTN_PIN, INPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(BL_RED_PIN, INPUT);
|
||||
pinMode(BL_GRN_PIN, INPUT);
|
||||
|
||||
ba_time = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Timeout protection
|
||||
if ((lastCommandTime + TIMEOUT < millis())) {
|
||||
floatResponse = 0.0;
|
||||
floatByte = 0;
|
||||
needFloat = false;
|
||||
autoResponse = TMO_RSP;
|
||||
}
|
||||
|
||||
//vcc = readvcc();
|
||||
|
||||
// stime = TimeToString(millis()/1000);
|
||||
// считываем точное напряжение с A0, где будет находиться наш вольтметр с делителем напряжения
|
||||
tin = 0.0;
|
||||
tdc = 0.0;
|
||||
tbt = 0.0;
|
||||
tba = 0.0;
|
||||
|
||||
for (byte i = 0; i < REP_COUNT; i++) {
|
||||
tin = tin * readvcc() + analogRead(VIN_PIN);
|
||||
tdc = tdc * readvcc() + analogRead(VDC_PIN);
|
||||
tbt = tbt * readvcc() + analogRead(VBT_PIN);
|
||||
tba = tba * readvcc() + analogRead(VBA_PIN);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// tin = (tin * vcc) / 1024.0 / kin / REP_COUNT;
|
||||
// tdc = (tdc * vcc) / 1024.0 / kdc / REP_COUNT;
|
||||
// tbt = (tbt * vcc) / 1024.0 / kbt / REP_COUNT;
|
||||
// tba = (tba * vcc) / 1024.0 / kba / REP_COUNT;
|
||||
|
||||
tin = tin / 1024.0 / kin / REP_COUNT;
|
||||
tdc = tdc / 1024.0 / kdc / REP_COUNT;
|
||||
tbt = tbt / 1024.0 / kbt / REP_COUNT;
|
||||
tba = tba / 1024.0 / kba / REP_COUNT;
|
||||
|
||||
vin = tin;
|
||||
vdc = tdc;
|
||||
vbt = tbt;
|
||||
if (ba_enabled) vba = tba;
|
||||
|
||||
// if (DEBUG && count >= 5) {
|
||||
// Serial.print("Vcc= ");
|
||||
// Serial.println(vcc);
|
||||
// Serial.print("Vin= ");
|
||||
// Serial.println(vin);
|
||||
// Serial.print("Vdc= ");
|
||||
// Serial.println(vdc);
|
||||
// Serial.print("Vbt= ");
|
||||
// Serial.println(vbt);
|
||||
// Serial.print("Vpf= ");
|
||||
// Serial.println(vpf);
|
||||
// Serial.println("---");
|
||||
// count = 0;
|
||||
// }
|
||||
// else count++;
|
||||
|
||||
// Vin check
|
||||
if (vin >= VIN_MIN && vin <= VIN_MAX) {
|
||||
if (! vin_ok) vin_count++;
|
||||
}
|
||||
else {
|
||||
vin_count = 0;
|
||||
vin_ok = false;
|
||||
}
|
||||
|
||||
if (vin_count >= V_CHECK_CYCLES) vin_ok = true;
|
||||
|
||||
// Vdc check
|
||||
if (vdc >= VDC_MIN && vdc <= VDC_MAX) {
|
||||
if (! vdc_ok) vdc_count++;
|
||||
}
|
||||
else {
|
||||
vdc_count = 0;
|
||||
vdc_ok = false;
|
||||
}
|
||||
|
||||
if (vdc_count >= V_CHECK_CYCLES) vdc_ok = true;
|
||||
|
||||
// Vbt check
|
||||
if (vbt >= VBT_MIN && vbt <= VBT_MAX) {
|
||||
if (! vbt_ok) vbt_count++;
|
||||
}
|
||||
else {
|
||||
vbt_count = 0;
|
||||
vbt_ok = false;
|
||||
}
|
||||
|
||||
if (vbt_count >= V_CHECK_CYCLES) vbt_ok = true;
|
||||
|
||||
// Vba check
|
||||
if (ba_enabled) {
|
||||
if (vba >= VBA_MIN && vba <= VBA_MAX) {
|
||||
if (! vba_ok) vba_count++;
|
||||
}
|
||||
else {
|
||||
vba_count = 0;
|
||||
vba_ok = false;
|
||||
}
|
||||
|
||||
if (vba_count >= V_CHECK_CYCLES) vba_ok = true;
|
||||
}
|
||||
else {
|
||||
//vba = 0.0;
|
||||
vba_ok = false;
|
||||
}
|
||||
|
||||
// Vcc check
|
||||
if (vcc >= VCC_MIN && vcc <= VCC_MAX) {
|
||||
if (! vcc_ok) vcc_count++;
|
||||
}
|
||||
else {
|
||||
vcc_count = 0;
|
||||
vcc_ok = false;
|
||||
}
|
||||
|
||||
if (vcc_count >= V_CHECK_CYCLES) vcc_ok = true;
|
||||
|
||||
// Auto switch to BA
|
||||
if (! vin_ok) {
|
||||
switchToBA();
|
||||
}
|
||||
|
||||
// BL status
|
||||
bl_powered = false;
|
||||
bl_error = false;
|
||||
ba_full = false;
|
||||
ba_charge = false;
|
||||
|
||||
if (vin_ok && bl_enabled) {
|
||||
delay_time = 0;
|
||||
|
||||
// if (DEBUG) {
|
||||
// unsigned long tmp1, tmp2;
|
||||
//
|
||||
// tmp1 = millis();
|
||||
// while(digitalRead(BL_GRN_PIN) == LOW) {
|
||||
//
|
||||
// }
|
||||
// tmp2 = millis();
|
||||
//
|
||||
// Serial.print("time1: ");
|
||||
// Serial.println(tmp2 - tmp1);
|
||||
//
|
||||
// tmp1 = millis();
|
||||
// while(digitalRead(BL_GRN_PIN) == HIGH) {
|
||||
//
|
||||
// }
|
||||
// tmp2 = millis();
|
||||
// Serial.print("time2: ");
|
||||
// Serial.println(tmp2 - tmp1);
|
||||
//
|
||||
// }
|
||||
|
||||
switch (detectBlink(BL_GRN_PIN)) {
|
||||
case 0:
|
||||
ba_full = false;
|
||||
ba_charge = false;
|
||||
break;
|
||||
case 1:
|
||||
ba_full = true;
|
||||
ba_charge = false;
|
||||
bl_powered = true;
|
||||
break;
|
||||
case 2:
|
||||
ba_full = false;
|
||||
ba_charge = true;
|
||||
bl_powered = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! ba_charge && ! ba_full) {
|
||||
switch (detectBlink(BL_RED_PIN)) {
|
||||
case 0:
|
||||
bl_powered = false;
|
||||
bl_error = false;
|
||||
break;
|
||||
case 1:
|
||||
bl_powered = true;
|
||||
bl_error = false;
|
||||
break;
|
||||
case 2:
|
||||
bl_powered = false;
|
||||
bl_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else delay_time = DELAY_TIME;
|
||||
|
||||
// Button reaction
|
||||
if (digitalRead(BTN_PIN) == HIGH) {
|
||||
if (button_count >= BUTTON_CYCLES) {
|
||||
if (ba_enabled && vin_ok) {
|
||||
switchToIN();
|
||||
}
|
||||
else {
|
||||
switchToBA();
|
||||
ba_blocked = true;
|
||||
}
|
||||
button_count = 0;
|
||||
}
|
||||
else button_count++;
|
||||
}
|
||||
else button_count = 0;
|
||||
|
||||
// Disable BA block
|
||||
if (ba_blocked && ba_time + BA_BLOCK_TIMEOUT < millis()) {
|
||||
ba_blocked = false;
|
||||
}
|
||||
|
||||
// Auto switch to IN
|
||||
if (vin_ok && ba_enabled && ! ba_blocked && ba_time + BA_TIMEOUT < millis()) {
|
||||
switchToIN();
|
||||
}
|
||||
|
||||
// Auto enable BL
|
||||
if (! pf_enabled && ! ba_enabled && vin_ok) {
|
||||
enableBL();
|
||||
}
|
||||
|
||||
status_1 = 0x00;
|
||||
if (vcc_ok) status_1 |= 0x01;
|
||||
if (vin_ok) status_1 |= 0x02;
|
||||
if (vdc_ok) status_1 |= 0x04;
|
||||
if (vbt_ok) status_1 |= 0x08;
|
||||
if (vba_ok) status_1 |= 0x10;
|
||||
if (lr_enabled) status_1 |= 0x20;
|
||||
if (ba_enabled) status_1 |= 0x40;
|
||||
if (ba_blocked) status_1 |= 0x80;
|
||||
|
||||
status_2 = 0x00;
|
||||
if (bl_powered) status_2 |= 0x01;
|
||||
if (bl_error) status_2 |= 0x02;
|
||||
if (ba_full) status_2 |= 0x04;
|
||||
if (ba_charge) status_2 |= 0x08;
|
||||
// if (vpf_low) status_2 |= 0x10;
|
||||
// if (vpf_high) status_2 |= 0x20;
|
||||
if (pf_enabled) status_2 |= 0x40;
|
||||
if (bl_enabled) status_2 |= 0x80;
|
||||
|
||||
// Delay
|
||||
delay(delay_time);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Функции
|
||||
****************************************************************************/
|
||||
|
||||
float readvcc() {
|
||||
byte i;
|
||||
float result = 0.0;
|
||||
float tmp = 0.0;
|
||||
|
||||
for (i = 0; i < REP_COUNT; i++) {
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
result = result + tmp;
|
||||
delay(5);
|
||||
}
|
||||
|
||||
result = result / REP_COUNT;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
ext = Wire.read();
|
||||
if (ext == EXT_COM && byteCount == 3) {
|
||||
cmd = 0x00;
|
||||
sum = 0x00;
|
||||
|
||||
if (Wire.available()) sum = Wire.read();
|
||||
if (Wire.available()) cmd = Wire.read();
|
||||
|
||||
if ((cmd ^ XOR_SEQ) != sum) {
|
||||
autoResponse = CSE_RSP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
autoResponse = ERR_RSP;
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process command
|
||||
switch (cmd) {
|
||||
case COM_GET_VIN:
|
||||
sendFloat(vin);
|
||||
break;
|
||||
case COM_GET_VDC:
|
||||
sendFloat(vdc);
|
||||
break;
|
||||
case COM_GET_VBT:
|
||||
sendFloat(vbt);
|
||||
break;
|
||||
case COM_GET_VBA:
|
||||
sendFloat(vba);
|
||||
break;
|
||||
case COM_GET_VCC:
|
||||
sendFloat(vcc);
|
||||
break;
|
||||
case COM_GET_TEMP:
|
||||
sendFloat(getInternalTemp());
|
||||
break;
|
||||
case COM_GET_STAT1:
|
||||
sendByte(status_1);
|
||||
break;
|
||||
case COM_GET_STAT2:
|
||||
sendByte(status_2);
|
||||
break;
|
||||
|
||||
case COM_POWER_ON_BL:
|
||||
digitalWrite(R_BL, HIGH);
|
||||
bl_enabled = true;
|
||||
commandResponse();
|
||||
break;
|
||||
case COM_SHUTDOWN_BL:
|
||||
digitalWrite(R_BL, LOW);
|
||||
bl_enabled = false;
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_POWER_ON_PF:
|
||||
digitalWrite(R_PF, HIGH);
|
||||
pf_enabled = true;
|
||||
commandResponse();
|
||||
break;
|
||||
case COM_SHUTDOWN_PF:
|
||||
digitalWrite(R_PF, LOW);
|
||||
pf_enabled = false;
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_SWITCH_TO_IS:
|
||||
commandResponse(switchToIS());
|
||||
break;
|
||||
case COM_SWITCH_TO_LR:
|
||||
commandResponse(switchToLR());
|
||||
break;
|
||||
|
||||
case COM_SWITCH_TO_IN:
|
||||
commandResponse(switchToIN());
|
||||
break;
|
||||
case COM_SWITCH_TO_BA:
|
||||
commandResponse(switchToBA());
|
||||
break;
|
||||
|
||||
case COM_ENABLE_PF:
|
||||
enablePF();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_PF:
|
||||
disablePF();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_ENABLE_BL:
|
||||
enableBL();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_BL:
|
||||
disableBL();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
default:
|
||||
autoResponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void commandResponse() {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = OK_RSP;
|
||||
}
|
||||
|
||||
void commandResponse(byte response) {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = response;
|
||||
}
|
||||
|
||||
void sendByte(byte value) {
|
||||
lastCommandTime = millis();
|
||||
byteResponse = value;
|
||||
needSumm = false;
|
||||
needByte = true;
|
||||
}
|
||||
|
||||
void sendFloat(float value) {
|
||||
lastCommandTime = millis();
|
||||
floatResponse = value;
|
||||
floatByte = 0;
|
||||
needFloat = true;
|
||||
}
|
||||
|
||||
byte cSum(byte value) {
|
||||
return value ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
byte cSum(byte *data, byte dataSize) {
|
||||
byte tmp = 0x00;
|
||||
for (byte i = 0; i < dataSize; i++) {
|
||||
tmp = tmp ^ data[i];
|
||||
}
|
||||
return tmp ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
void answer() {
|
||||
// Want float value?
|
||||
if (needFloat) {
|
||||
// Get access to the float as a byte-array:
|
||||
byte *data = (byte *) &floatResponse;
|
||||
|
||||
if (floatByte < sizeof(floatResponse)) {
|
||||
// Send byte
|
||||
Wire.write(data[floatByte]);
|
||||
floatByte++;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(data, sizeof(floatResponse)));
|
||||
needFloat = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want byte value?
|
||||
if (needByte) {
|
||||
if (!needSumm) {
|
||||
// Send byte
|
||||
Wire.write(byteResponse);
|
||||
needSumm = true;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(byteResponse));
|
||||
needSumm = false;
|
||||
needByte = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want something else?
|
||||
Wire.write(autoResponse);
|
||||
}
|
||||
}
|
||||
// Nothing more to send
|
||||
autoResponse = NO_RSP;
|
||||
}
|
||||
|
||||
byte switchToLR() {
|
||||
if (vbt_ok) {
|
||||
digitalWrite(R_HX, LOW);
|
||||
lr_enabled = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte switchToIS() {
|
||||
digitalWrite(R_HX, HIGH);
|
||||
lr_enabled = false;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
|
||||
byte switchToBA() {
|
||||
if (! ba_enabled) {
|
||||
|
||||
// Disable BL
|
||||
if (bl_enabled) {
|
||||
digitalWrite(R_BL, LOW);
|
||||
bl_enabled = false;
|
||||
//delay(500);
|
||||
}
|
||||
|
||||
digitalWrite(R_IS, LOW);
|
||||
ba_enabled = true;
|
||||
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
ba_time = millis();
|
||||
ba_blocked = true;
|
||||
}
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
|
||||
byte switchToIN() {
|
||||
if (vin_ok && ba_enabled) {
|
||||
digitalWrite(R_IS, HIGH);
|
||||
ba_enabled = false;
|
||||
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
void enablePF() {
|
||||
if (bl_enabled) {
|
||||
digitalWrite(R_BL, LOW);
|
||||
bl_enabled = false;
|
||||
//delay(500);
|
||||
}
|
||||
digitalWrite(R_PF, HIGH);
|
||||
pf_enabled = true;
|
||||
}
|
||||
|
||||
void disablePF() {
|
||||
digitalWrite(R_PF, LOW);
|
||||
pf_enabled = false;
|
||||
}
|
||||
|
||||
byte enableBL() {
|
||||
if (! ba_enabled && ! pf_enabled) {
|
||||
digitalWrite(R_BL, HIGH);
|
||||
bl_enabled = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
void disableBL() {
|
||||
digitalWrite(R_BL, LOW);
|
||||
bl_enabled = false;
|
||||
}
|
||||
|
||||
// Get the internal temperature
|
||||
float getInternalTemp() {
|
||||
unsigned int wADC;
|
||||
float t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return(t);
|
||||
}
|
||||
|
||||
byte detectBlink(byte pin) {
|
||||
// Return codes:
|
||||
// 0 - LOW
|
||||
// 1 - HIGH
|
||||
// 2 - BLINK
|
||||
byte low_count = 0;
|
||||
byte high_count = 0;
|
||||
byte i = 0;
|
||||
byte pin_level;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
pin_level = digitalRead(pin);
|
||||
if (pin_level == HIGH) high_count++;
|
||||
if (pin_level == LOW) low_count++;
|
||||
delay(300);
|
||||
}
|
||||
|
||||
if (low_count > 0 && high_count == 0)
|
||||
return 0;
|
||||
else
|
||||
if (high_count > 0 && low_count == 0)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
1051
HXpower2/HXpower2.ino
Normal file
1051
HXpower2/HXpower2.ino
Normal file
File diff suppressed because it is too large
Load Diff
899
HXpower3/HXpower3.ino
Normal file
899
HXpower3/HXpower3.ino
Normal file
@ -0,0 +1,899 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot HXpower firmware /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 0
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x05
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
#define AIN_PIN A9
|
||||
#define ADC_PIN A8
|
||||
#define AUS_PIN A7
|
||||
#define ABA_PIN A6
|
||||
|
||||
#define VIN_PIN A5
|
||||
#define VDC_PIN A4
|
||||
#define VBT_PIN A3
|
||||
#define VBA_PIN A2
|
||||
#define VZU_PIN A1
|
||||
#define VPF_PIN A0
|
||||
|
||||
#define R_BA 11
|
||||
#define R_PF 5
|
||||
#define R_DC 1
|
||||
#define R_US 7
|
||||
//#define RED_PIN 10
|
||||
//#define GRN_PIN 12
|
||||
#define INC_PIN 0
|
||||
#define LED_PIN 13
|
||||
|
||||
#define REP_COUNT 5
|
||||
|
||||
#define TIMEOUT 5000
|
||||
#define BUTTON_REACTION_TIME 5000
|
||||
|
||||
// COMMANDS
|
||||
// VOLTMETERS
|
||||
#define COM_GET_VIN 0x01
|
||||
#define COM_GET_VDC 0x02
|
||||
#define COM_GET_VBT 0x03
|
||||
#define COM_GET_VBA 0x04
|
||||
#define COM_GET_VPF 0x05
|
||||
#define COM_GET_VZU 0x06
|
||||
#define COM_GET_VCC 0x07
|
||||
|
||||
// AMPERMETERS
|
||||
#define COM_GET_AUS 0x21
|
||||
#define COM_GET_ABA 0x22
|
||||
#define COM_GET_AIN 0x23
|
||||
#define COM_GET_ADC 0x24
|
||||
|
||||
// STATUS
|
||||
#define COM_GET_STAT1 0x08
|
||||
#define COM_GET_STAT2 0x09
|
||||
#define COM_GET_STAT3 0x20
|
||||
|
||||
// TEMP
|
||||
#define COM_GET_TEMP 0x10
|
||||
|
||||
// RELAYS
|
||||
#define COM_ENABLE_BA 0x11 // 17
|
||||
#define COM_ENABLE_PF 0x12 // 18
|
||||
#define COM_ENABLE_EX 0x13 // 19
|
||||
#define COM_ENABLE_US 0x14 // 20
|
||||
|
||||
#define COM_DISABLE_BA 0x15 // 21
|
||||
#define COM_DISABLE_PF 0x16 // 22
|
||||
#define COM_DISABLE_EX 0x17 // 23
|
||||
#define COM_DISABLE_US 0x18 // 24
|
||||
|
||||
#define COM_RUN 0x1B // 27
|
||||
#define COM_STOP 0x1C // 28
|
||||
#define COM_RESET_US 0x1D // 29
|
||||
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// CONST
|
||||
#define EX_BLOCK_TIMEOUT 30000
|
||||
#define BA_BLOCK_TIMEOUT 30000
|
||||
#define BA_FULL_CHECK_CYCLES 20
|
||||
#define V_CHECK_CYCLES 10
|
||||
//#define MAX_VBT_FAIL 15
|
||||
#define AREF 5
|
||||
|
||||
#define VIN_MIN 14.0
|
||||
#define VIN_MAX 20.0
|
||||
|
||||
#define VDC_MIN 5.0
|
||||
#define VDC_MAX 6.5
|
||||
|
||||
#define VBT_MIN 6.6
|
||||
#define VBT_MAX 8.6
|
||||
|
||||
#define VBA_MIN 9.0
|
||||
#define VBA_MAX 13.0
|
||||
#define VBA_FULL 12.0
|
||||
|
||||
#define VPF_MIN 7.2
|
||||
#define VPF_MAX 10.0
|
||||
|
||||
#define VZU_MIN 5.0
|
||||
#define VZU_MAX 6.3
|
||||
|
||||
#define VCC_MIN 4.3
|
||||
#define VCC_MAX 5.3
|
||||
|
||||
#define AUS_MIN 0.1
|
||||
#define AUS_MAX 5.0
|
||||
|
||||
#define ABA_MIN 0.1
|
||||
#define ABA_MAX 5.0
|
||||
|
||||
#define AIN_MIN 0.1
|
||||
#define AIN_MAX 5.0
|
||||
|
||||
#define ADC_MIN 0.1
|
||||
#define ADC_MAX 5.0
|
||||
|
||||
// VAR
|
||||
// резисторы делителя напряжения
|
||||
const float r1_1 = 20000; // 20K
|
||||
const float r1_2 = 10000; // 10K
|
||||
const float r2_1 = 10380; // 10K
|
||||
const float r2_2 = 10000; // 10K
|
||||
const float r3_1 = 10000; // 10K
|
||||
const float r3_2 = 10000; // 10K
|
||||
const float r4_1 = 20330; // 20K
|
||||
const float r4_2 = 10000; // 10K
|
||||
const float r5_1 = 1060; // 1K
|
||||
const float r5_2 = 1000; // 1K
|
||||
const float r6_1 = 1000; // 1K
|
||||
const float r6_2 = 1000; // 1K
|
||||
|
||||
// эту константу (typVbg) необходимо откалибровать индивидуально
|
||||
const float typVbg = 1.08; // 1.0 -- 1.2
|
||||
|
||||
float vcc = 0.0, tcc;
|
||||
float kin, kdc, kbt, kba, kpf, kzu;
|
||||
float vin, vdc, vbt, vba, vpf, vzu;
|
||||
float tin, tdc, tbt, tba, tpf, tzu;
|
||||
float aus, aba, ain, adc;
|
||||
float uus, uba, uin, udc;
|
||||
|
||||
byte cmd = 0x00;
|
||||
byte ext = 0x00;
|
||||
byte sum = 0x00;
|
||||
|
||||
unsigned long lastCommandTime = 0;
|
||||
byte autoResponse = 0x00;
|
||||
|
||||
byte byteResponse = 0x00;
|
||||
boolean needByte = false;
|
||||
boolean needSumm = false;
|
||||
|
||||
float floatResponse = 0.0;
|
||||
boolean needFloat = false;
|
||||
byte floatByte = 0;
|
||||
|
||||
unsigned long ex_time, ba_time;
|
||||
boolean ex_blocked = false, ba_blocked = false;
|
||||
|
||||
byte ba_full_count = 0;
|
||||
|
||||
//boolean ex_requested = false;
|
||||
|
||||
unsigned long inc_time;
|
||||
|
||||
boolean vin_ok = false;
|
||||
byte vin_count = 0;
|
||||
|
||||
boolean vdc_ok = false;
|
||||
byte vdc_count = 0;
|
||||
|
||||
boolean vbt_ok = false, vbt_fail = false;
|
||||
byte vbt_count = 0, vbt_fail_count = 0;
|
||||
|
||||
boolean vba_ok = false;
|
||||
byte vba_count = 0;
|
||||
|
||||
boolean vpf_ok = false;
|
||||
byte vpf_count = 0;
|
||||
|
||||
boolean vzu_ok = false;
|
||||
byte vzu_count = 0;
|
||||
|
||||
boolean vcc_ok = false;
|
||||
byte vcc_count = 0;
|
||||
|
||||
boolean aus_ok = false;
|
||||
byte aus_count = 0;
|
||||
|
||||
boolean aba_ok = false;
|
||||
byte aba_count = 0;
|
||||
|
||||
boolean ain_ok = false;
|
||||
byte ain_count = 0;
|
||||
|
||||
boolean adc_ok = false;
|
||||
byte adc_count = 0;
|
||||
|
||||
boolean ba_enabled = false;
|
||||
boolean ex_enabled = false;
|
||||
boolean pf_enabled = false;
|
||||
boolean us_enabled = true;
|
||||
|
||||
boolean ba_full = false;
|
||||
boolean ba_charge = false;
|
||||
|
||||
byte status_1 = 0x00;
|
||||
byte status_2 = 0x00;
|
||||
byte status_3 = 0x00;
|
||||
|
||||
/****************************************************************************
|
||||
* Главная программа
|
||||
****************************************************************************/
|
||||
|
||||
void setup() {
|
||||
if (DEBUG) {
|
||||
Serial.begin(9600);
|
||||
Serial.println("---");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// определение опорного напряжения
|
||||
analogReference(DEFAULT); // DEFAULT INTERNAL использовать vcc как AREF
|
||||
|
||||
kin = r1_2 / (r1_1 + r1_2);
|
||||
kdc = r2_2 / (r2_1 + r2_2);
|
||||
kbt = r3_2 / (r3_1 + r3_2);
|
||||
kba = r4_2 / (r4_1 + r4_2);
|
||||
kpf = r5_2 / (r5_1 + r5_2);
|
||||
kzu = r6_2 / (r6_1 + r6_2);
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc= ");
|
||||
Serial.println(vcc);
|
||||
Serial.println("---");
|
||||
}
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
pinMode(R_BA, OUTPUT);
|
||||
pinMode(R_PF, OUTPUT);
|
||||
pinMode(R_DC, OUTPUT);
|
||||
pinMode(R_US, OUTPUT);
|
||||
|
||||
pinMode(VIN_PIN, INPUT);
|
||||
pinMode(VDC_PIN, INPUT);
|
||||
pinMode(VBT_PIN, INPUT);
|
||||
pinMode(VBA_PIN, INPUT);
|
||||
pinMode(VPF_PIN, INPUT);
|
||||
pinMode(VZU_PIN, INPUT);
|
||||
|
||||
pinMode(AUS_PIN, INPUT);
|
||||
pinMode(ABA_PIN, INPUT);
|
||||
pinMode(AIN_PIN, INPUT);
|
||||
pinMode(ADC_PIN, INPUT);
|
||||
|
||||
pinMode(INC_PIN, INPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
ex_time = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Timeout protection
|
||||
if ((lastCommandTime + TIMEOUT < millis())) {
|
||||
floatResponse = 0.0;
|
||||
floatByte = 0;
|
||||
needFloat = false;
|
||||
autoResponse = TMO_RSP;
|
||||
}
|
||||
|
||||
// BLOCK OF MAGIC
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
// MAGIC
|
||||
|
||||
// Get voltages
|
||||
tin = 0.0;
|
||||
tdc = 0.0;
|
||||
tbt = 0.0;
|
||||
tba = 0.0;
|
||||
tpf = 0.0;
|
||||
tzu = 0.0;
|
||||
|
||||
tin += readvcc() * analogRead(VIN_PIN);
|
||||
tdc += readvcc() * analogRead(VDC_PIN);
|
||||
tbt += readvcc() * analogRead(VBT_PIN);
|
||||
tba += readvcc() * analogRead(VBA_PIN);
|
||||
tpf += readvcc() * analogRead(VPF_PIN);
|
||||
tzu += readvcc() * analogRead(VZU_PIN);
|
||||
|
||||
tcc = readvcc();
|
||||
tin = tin / 1024.0 / kin;// / REP_COUNT;
|
||||
tdc = tdc / 1024.0 / kdc;// / REP_COUNT;
|
||||
tbt = tbt / 1024.0 / kbt;// / REP_COUNT;
|
||||
tba = tba / 1024.0 / kba;// / REP_COUNT;
|
||||
tpf = tpf / 1024.0 / kpf;// / REP_COUNT;
|
||||
tzu = tzu / 1024.0 / kzu;// / REP_COUNT;
|
||||
|
||||
if (tcc > VCC_MIN) vcc = tcc;
|
||||
vin = tin;
|
||||
vdc = tdc;
|
||||
vbt = tbt;
|
||||
vba = tba;
|
||||
vpf = tpf;
|
||||
vzu = tzu;
|
||||
|
||||
// Get currents
|
||||
aus = (analogRead(AUS_PIN) - 512) * 0.0264;
|
||||
//if (aus < 0) aus *= -1;
|
||||
aba = (analogRead(ABA_PIN) - 512) * 0.0264;
|
||||
//if (aba < 0) aba *= -1;
|
||||
ain = (analogRead(AIN_PIN) - 512) * 0.0264;
|
||||
//if (ain < 0) ain *= -1;
|
||||
adc = (analogRead(ADC_PIN) - 512) * 0.0264;
|
||||
//if (adc < 0) adc *= -1;
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc: ");
|
||||
Serial.println(vcc);
|
||||
Serial.print("Vin: ");
|
||||
Serial.println(vin);
|
||||
Serial.print("Vdc: ");
|
||||
Serial.println(vdc);
|
||||
Serial.print("Vbt: ");
|
||||
Serial.println(vbt);
|
||||
Serial.print("Vba: ");
|
||||
Serial.println(vba);
|
||||
Serial.print("Vpf: ");
|
||||
Serial.println(vpf);
|
||||
Serial.print("Vzu: ");
|
||||
Serial.println(vzu);
|
||||
Serial.println("---");
|
||||
}
|
||||
|
||||
// Vin check
|
||||
if (vin >= VIN_MIN && vin <= VIN_MAX) {
|
||||
if (! vin_ok) vin_count++;
|
||||
}
|
||||
else {
|
||||
vin_count = 0;
|
||||
vin_ok = false;
|
||||
}
|
||||
|
||||
if (vin_count >= V_CHECK_CYCLES) vin_ok = true;
|
||||
|
||||
// Vdc check
|
||||
if (vdc >= VDC_MIN && vdc <= VDC_MAX) {
|
||||
if (! vdc_ok) vdc_count++;
|
||||
}
|
||||
else {
|
||||
vdc_count = 0;
|
||||
vdc_ok = false;
|
||||
}
|
||||
|
||||
if (vdc_count >= V_CHECK_CYCLES) vdc_ok = true;
|
||||
|
||||
// Vbt check
|
||||
if (vbt >= VBT_MIN && vbt <= VBT_MAX) {
|
||||
if (! vbt_ok) vbt_count++;
|
||||
}
|
||||
else {
|
||||
vbt_count = 0;
|
||||
vbt_ok = false;
|
||||
}
|
||||
|
||||
if (vbt_count >= V_CHECK_CYCLES) vbt_ok = true;
|
||||
|
||||
// Vba check
|
||||
if (vba >= VBA_MIN && vba <= VBA_MAX) {
|
||||
if (! vba_ok) vba_count++;
|
||||
}
|
||||
else {
|
||||
vba_count = 0;
|
||||
vba_ok = false;
|
||||
}
|
||||
|
||||
if (vba_count >= V_CHECK_CYCLES) vba_ok = true;
|
||||
|
||||
// Vpf check
|
||||
if (vpf >= VPF_MIN && vpf <= VPF_MAX) {
|
||||
if (! vpf_ok) vpf_count++;
|
||||
}
|
||||
else {
|
||||
vpf_count = 0;
|
||||
vpf_ok = false;
|
||||
}
|
||||
|
||||
if (vpf_count >= V_CHECK_CYCLES) vpf_ok = true;
|
||||
|
||||
// Vzu check
|
||||
if (vzu >= VZU_MIN && vzu <= VZU_MAX) {
|
||||
if (! vzu_ok) vzu_count++;
|
||||
}
|
||||
else {
|
||||
vzu_count = 0;
|
||||
vzu_ok = false;
|
||||
}
|
||||
|
||||
if (vzu_count >= V_CHECK_CYCLES) vzu_ok = true;
|
||||
|
||||
// Vcc check
|
||||
if (vcc >= VCC_MIN && vcc <= VCC_MAX) {
|
||||
if (! vcc_ok) vcc_count++;
|
||||
}
|
||||
else {
|
||||
vcc_count = 0;
|
||||
vcc_ok = false;
|
||||
}
|
||||
|
||||
if (vcc_count >= V_CHECK_CYCLES) vcc_ok = true;
|
||||
|
||||
// Aus check
|
||||
if (aus >= AUS_MIN && aus <= AUS_MAX) {
|
||||
if (! aus_ok) aus_count++;
|
||||
}
|
||||
else {
|
||||
aus_count = 0;
|
||||
aus_ok = false;
|
||||
}
|
||||
|
||||
if (aus_count >= V_CHECK_CYCLES) aus_ok = true;
|
||||
|
||||
// Aba check
|
||||
if (aba >= ABA_MIN && aba <= ABA_MAX) {
|
||||
if (! aba_ok) aba_count++;
|
||||
}
|
||||
else {
|
||||
aba_count = 0;
|
||||
aba_ok = false;
|
||||
}
|
||||
|
||||
if (aba_count >= V_CHECK_CYCLES) aba_ok = true;
|
||||
|
||||
// Ain check
|
||||
if (ain >= AIN_MIN && ain <= AIN_MAX) {
|
||||
if (! ain_ok) ain_count++;
|
||||
}
|
||||
else {
|
||||
ain_count = 0;
|
||||
ain_ok = false;
|
||||
}
|
||||
|
||||
if (ain_count >= V_CHECK_CYCLES) ain_ok = true;
|
||||
|
||||
// Adc check
|
||||
if (adc >= ADC_MIN && adc <= ADC_MAX) {
|
||||
if (! adc_ok) adc_count++;
|
||||
}
|
||||
else {
|
||||
adc_count = 0;
|
||||
adc_ok = false;
|
||||
}
|
||||
|
||||
if (adc_count >= V_CHECK_CYCLES) adc_ok = true;
|
||||
|
||||
// BA full?
|
||||
if (vba >= VBA_FULL) {
|
||||
if (! ba_full && ! ba_enabled) ba_full_count++;
|
||||
}
|
||||
else {
|
||||
ba_full_count = 0;
|
||||
//ba_full = false;
|
||||
}
|
||||
|
||||
if (ba_full_count >= BA_FULL_CHECK_CYCLES) {
|
||||
ba_full = true;
|
||||
}
|
||||
|
||||
if (ba_enabled && ! in_plugged()) {
|
||||
ba_full = false;
|
||||
}
|
||||
|
||||
// Auto disable EX
|
||||
if (! vdc_ok) { // || ((! vin_ok || ! in_plugged()) && ! ex_requested)) {
|
||||
disableEX();
|
||||
}
|
||||
|
||||
// Disable EX block
|
||||
if (ex_blocked && ex_time + EX_BLOCK_TIMEOUT < millis()) {
|
||||
ex_blocked = false;
|
||||
}
|
||||
|
||||
// Auto enable EX
|
||||
if (vdc_ok && ! ex_blocked) {
|
||||
enableEX();
|
||||
}
|
||||
|
||||
// Auto enable BA (for charge)
|
||||
if (! ba_enabled && vin_ok && in_plugged() && ! ba_full && ! ba_blocked) {
|
||||
enableBA();
|
||||
}
|
||||
|
||||
// Auto disable BA (if charge complete)
|
||||
if (ba_enabled && ba_full && in_plugged()) { //(ba_full || ! in_plugged())) {
|
||||
disableBA();
|
||||
}
|
||||
|
||||
// Auto enable BA (for support)
|
||||
if (! ba_enabled && ! ba_blocked && (! vin_ok || ! in_plugged())) {
|
||||
enableBA();
|
||||
}
|
||||
|
||||
// Auto disable BA (if discharged)
|
||||
if (ba_enabled && ! in_plugged() && ! vba_ok) {
|
||||
disableBA();
|
||||
}
|
||||
|
||||
// Disable BA block
|
||||
if (ba_blocked && ba_time + BA_BLOCK_TIMEOUT < millis()) {
|
||||
ba_blocked = false;
|
||||
}
|
||||
|
||||
// Compile status
|
||||
status_1 = 0x00;
|
||||
if (vcc_ok) status_1 |= 0x01;
|
||||
if (vin_ok) status_1 |= 0x02;
|
||||
if (vdc_ok) status_1 |= 0x04;
|
||||
if (vbt_ok) status_1 |= 0x08;
|
||||
if (vba_ok) status_1 |= 0x10;
|
||||
if (ex_enabled) status_1 |= 0x20;
|
||||
if (ba_enabled) status_1 |= 0x40;
|
||||
if (ex_blocked) status_1 |= 0x80;
|
||||
|
||||
status_2 = 0x00;
|
||||
if (in_plugged()) status_2 |= 0x01;
|
||||
if (ba_blocked) status_2 |= 0x02;
|
||||
if (ba_full) status_2 |= 0x04;
|
||||
if (ba_charge) status_2 |= 0x08;
|
||||
if (vpf_ok) status_2 |= 0x10;
|
||||
if (vzu_ok) status_2 |= 0x20;
|
||||
if (pf_enabled) status_2 |= 0x40;
|
||||
if (us_enabled) status_2 |= 0x80;
|
||||
|
||||
status_3 = 0x00;
|
||||
if (aus_ok) status_3 |= 0x01;
|
||||
if (aba_ok) status_3 |= 0x02;
|
||||
if (ain_ok) status_3 |= 0x04;
|
||||
if (adc_ok) status_3 |= 0x08;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Функции
|
||||
****************************************************************************/
|
||||
|
||||
float readvcc() {
|
||||
byte i;
|
||||
float result = 0.0;
|
||||
float tmp = 0.0;
|
||||
|
||||
//for (i = 0; i < REP_COUNT; i++) {
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
//result = result + tmp;
|
||||
// delay(5);
|
||||
//}
|
||||
|
||||
//result = result / REP_COUNT;
|
||||
return tmp;//result;
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
ext = Wire.read();
|
||||
if (ext == EXT_COM && byteCount == 3) {
|
||||
cmd = 0x00;
|
||||
sum = 0x00;
|
||||
|
||||
if (Wire.available()) sum = Wire.read();
|
||||
if (Wire.available()) cmd = Wire.read();
|
||||
|
||||
if ((cmd ^ XOR_SEQ) != sum) {
|
||||
autoResponse = CSE_RSP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
autoResponse = ERR_RSP;
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process command
|
||||
switch (cmd) {
|
||||
case COM_GET_VIN:
|
||||
sendFloat(vin);
|
||||
break;
|
||||
case COM_GET_VDC:
|
||||
sendFloat(vdc);
|
||||
break;
|
||||
case COM_GET_VBT:
|
||||
sendFloat(vbt);
|
||||
break;
|
||||
case COM_GET_VBA:
|
||||
sendFloat(vba);
|
||||
break;
|
||||
case COM_GET_VPF:
|
||||
sendFloat(vpf);
|
||||
break;
|
||||
case COM_GET_VZU:
|
||||
sendFloat(vzu);
|
||||
break;
|
||||
case COM_GET_VCC:
|
||||
sendFloat(vcc);
|
||||
break;
|
||||
|
||||
case COM_GET_AUS:
|
||||
sendFloat(aus);
|
||||
break;
|
||||
case COM_GET_ABA:
|
||||
sendFloat(aba);
|
||||
break;
|
||||
case COM_GET_AIN:
|
||||
sendFloat(ain);
|
||||
break;
|
||||
case COM_GET_ADC:
|
||||
sendFloat(adc);
|
||||
break;
|
||||
|
||||
case COM_GET_TEMP:
|
||||
sendFloat(getInternalTemp());
|
||||
break;
|
||||
case COM_GET_STAT1:
|
||||
sendByte(status_1);
|
||||
break;
|
||||
case COM_GET_STAT2:
|
||||
sendByte(status_2);
|
||||
break;
|
||||
case COM_GET_STAT3:
|
||||
sendByte(status_3);
|
||||
break;
|
||||
|
||||
case COM_ENABLE_BA:
|
||||
commandResponse(enableBA());
|
||||
break;
|
||||
case COM_DISABLE_BA:
|
||||
commandResponse(disableBA());
|
||||
break;
|
||||
|
||||
case COM_ENABLE_EX:
|
||||
commandResponse(enableEX());
|
||||
break;
|
||||
case COM_DISABLE_EX:
|
||||
commandResponse(disableEX());
|
||||
break;
|
||||
|
||||
case COM_ENABLE_PF:
|
||||
enablePF();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_PF:
|
||||
disablePF();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_ENABLE_US:
|
||||
enableUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_US:
|
||||
disableUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_RESET_US:
|
||||
resetUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
default:
|
||||
autoResponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void commandResponse() {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = OK_RSP;
|
||||
}
|
||||
|
||||
void commandResponse(byte response) {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = response;
|
||||
}
|
||||
|
||||
void sendByte(byte value) {
|
||||
lastCommandTime = millis();
|
||||
byteResponse = value;
|
||||
needSumm = false;
|
||||
needByte = true;
|
||||
}
|
||||
|
||||
void sendFloat(float value) {
|
||||
lastCommandTime = millis();
|
||||
floatResponse = value;
|
||||
floatByte = 0;
|
||||
needFloat = true;
|
||||
}
|
||||
|
||||
byte cSum(byte value) {
|
||||
return value ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
byte cSum(byte *data, byte dataSize) {
|
||||
byte tmp = 0x00;
|
||||
for (byte i = 0; i < dataSize; i++) {
|
||||
tmp = tmp ^ data[i];
|
||||
}
|
||||
return tmp ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
void answer() {
|
||||
// Want float value?
|
||||
if (needFloat) {
|
||||
// Get access to the float as a byte-array:
|
||||
byte *data = (byte *) &floatResponse;
|
||||
|
||||
if (floatByte < sizeof(floatResponse)) {
|
||||
// Send byte
|
||||
Wire.write(data[floatByte]);
|
||||
floatByte++;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(data, sizeof(floatResponse)));
|
||||
needFloat = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want byte value?
|
||||
if (needByte) {
|
||||
if (!needSumm) {
|
||||
// Send byte
|
||||
Wire.write(byteResponse);
|
||||
needSumm = true;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(byteResponse));
|
||||
needSumm = false;
|
||||
needByte = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want something else?
|
||||
Wire.write(autoResponse);
|
||||
}
|
||||
}
|
||||
// Nothing more to send
|
||||
autoResponse = NO_RSP;
|
||||
}
|
||||
|
||||
byte enableEX() {
|
||||
if (vdc_ok) {
|
||||
digitalWrite(R_DC, HIGH);
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
ex_enabled = true;
|
||||
ex_blocked = false;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte disableEX() {
|
||||
if (vbt_ok) {
|
||||
digitalWrite(R_DC, LOW);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
ex_enabled = false;
|
||||
ex_time = millis();
|
||||
ex_blocked = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
void enablePF() {
|
||||
digitalWrite(R_PF, HIGH);
|
||||
pf_enabled = true;
|
||||
}
|
||||
|
||||
void disablePF() {
|
||||
digitalWrite(R_PF, LOW);
|
||||
pf_enabled = false;
|
||||
}
|
||||
|
||||
byte enableBA() {
|
||||
if (! (in_plugged() && ! vin_ok)) {
|
||||
digitalWrite(R_BA, HIGH);
|
||||
ba_enabled = true;
|
||||
ba_blocked = false;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte disableBA() {
|
||||
if (! (ex_enabled && ! in_plugged() && ! vbt_ok)) {
|
||||
digitalWrite(R_BA, LOW);
|
||||
ba_enabled = false;
|
||||
ba_time = millis();
|
||||
ba_blocked = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
void enableUS() {
|
||||
digitalWrite(R_US, LOW);
|
||||
us_enabled = true;
|
||||
}
|
||||
|
||||
void disableUS() {
|
||||
digitalWrite(R_US, HIGH);
|
||||
us_enabled = false;
|
||||
}
|
||||
|
||||
void resetUS() {
|
||||
disableUS();
|
||||
delay(500);
|
||||
enableUS();
|
||||
}
|
||||
|
||||
// Get the internal temperature
|
||||
float getInternalTemp() {
|
||||
unsigned int wADC;
|
||||
float t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return(t);
|
||||
}
|
||||
|
||||
bool in_plugged() {
|
||||
if (digitalRead(INC_PIN) == HIGH) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
897
HXpower4/HXpower4.ino
Normal file
897
HXpower4/HXpower4.ino
Normal file
@ -0,0 +1,897 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot HXpower firmware v4a /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 0
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x05
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
#define AIN_PIN A9
|
||||
#define ABT_PIN A8
|
||||
#define ABA_PIN A7
|
||||
#define AHX_PIN A6
|
||||
|
||||
#define VIN_PIN A5
|
||||
#define VDC_PIN A4
|
||||
#define VBT_PIN A3
|
||||
#define VBA_PIN A2
|
||||
#define VZU_PIN A1
|
||||
#define VPF_PIN A0
|
||||
|
||||
#define R_BT 11
|
||||
#define R_BA 7
|
||||
#define R_MV 5
|
||||
#define R_US 1
|
||||
//#define RED_PIN 10
|
||||
//#define GRN_PIN 12
|
||||
#define INC_PIN 0
|
||||
#define LED_PIN 13
|
||||
|
||||
#define REP_COUNT 5
|
||||
|
||||
#define TIMEOUT 5000
|
||||
#define BUTTON_REACTION_TIME 5000
|
||||
|
||||
// COMMANDS
|
||||
// VOLTMETERS
|
||||
#define COM_GET_VIN 0x01
|
||||
#define COM_GET_VDC 0x02
|
||||
#define COM_GET_VBT 0x03
|
||||
#define COM_GET_VBA 0x04
|
||||
#define COM_GET_VPF 0x05
|
||||
#define COM_GET_VZU 0x06
|
||||
#define COM_GET_VCC 0x07
|
||||
|
||||
// AMPERMETERS
|
||||
#define COM_GET_ABT 0x21
|
||||
#define COM_GET_ABA 0x22
|
||||
#define COM_GET_AIN 0x23
|
||||
#define COM_GET_AHX 0x24
|
||||
|
||||
// STATUS
|
||||
#define COM_GET_STAT1 0x08
|
||||
#define COM_GET_STAT2 0x09
|
||||
#define COM_GET_STAT3 0x20
|
||||
|
||||
// TEMP
|
||||
#define COM_GET_TEMP 0x10
|
||||
|
||||
// RELAYS
|
||||
#define COM_ENABLE_BA 0x11 // 17
|
||||
#define COM_ENABLE_MV 0x12 // 18
|
||||
#define COM_ENABLE_BT 0x13 // 19
|
||||
#define COM_ENABLE_US 0x14 // 20
|
||||
|
||||
#define COM_DISABLE_BA 0x15 // 21
|
||||
#define COM_DISABLE_MV 0x16 // 22
|
||||
#define COM_DISABLE_BT 0x17 // 23
|
||||
#define COM_DISABLE_US 0x18 // 24
|
||||
|
||||
#define COM_RUN 0x1B // 27
|
||||
#define COM_STOP 0x1C // 28
|
||||
#define COM_RESET_US 0x1D // 29
|
||||
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// CONST
|
||||
#define BT_BLOCK_TIMEOUT 30000
|
||||
#define BT_FULL_CHECK_CYCLES 20
|
||||
#define BA_BLOCK_TIMEOUT 30000
|
||||
#define BA_FULL_CHECK_CYCLES 20
|
||||
#define V_CHECK_CYCLES 10
|
||||
#define AREF 5
|
||||
|
||||
#define VIN_MIN 14.0
|
||||
#define VIN_MAX 25.0
|
||||
|
||||
#define VDC_MIN 5.5
|
||||
#define VDC_MAX 6.5
|
||||
|
||||
#define VBT_MIN 6.6
|
||||
#define VBT_MAX 8.6
|
||||
|
||||
#define VBA_MIN 9.0
|
||||
#define VBA_MAX 13.0
|
||||
#define VBA_FULL 12.0
|
||||
|
||||
#define VPF_MIN 7.2
|
||||
#define VPF_MAX 10.0
|
||||
|
||||
#define VZU_MIN 5.0
|
||||
#define VZU_MAX 6.3
|
||||
|
||||
#define VCC_MIN 4.8
|
||||
#define VCC_MAX 5.5
|
||||
|
||||
#define ABT_MIN 0.1
|
||||
#define ABT_MAX 5.0
|
||||
|
||||
#define ABA_MIN 0.1
|
||||
#define ABA_MAX 5.0
|
||||
|
||||
#define AIN_MIN 0.1
|
||||
#define AIN_MAX 5.0
|
||||
|
||||
#define AHX_MIN 0.1
|
||||
#define AHX_MAX 5.0
|
||||
|
||||
// VAR
|
||||
// резисторы делителя напряжения
|
||||
const float r1_1 = 100000; // 100K
|
||||
const float r1_2 = 10000; // 10K
|
||||
const float r2_1 = 10380; // 10K
|
||||
const float r2_2 = 10000; // 10K
|
||||
const float r3_1 = 20000; // 10K
|
||||
const float r3_2 = 10000; // 10K
|
||||
const float r4_1 = 20330; // 20K
|
||||
const float r4_2 = 10000; // 10K
|
||||
const float r5_1 = 1060; // 1K
|
||||
const float r5_2 = 1000; // 1K
|
||||
const float r6_1 = 1000; // 1K
|
||||
const float r6_2 = 1000; // 1K
|
||||
|
||||
// эту константу (typVbg) необходимо откалибровать индивидуально
|
||||
const float typVbg = 1.08; // 1.0 -- 1.2
|
||||
|
||||
float vcc = 0.0, tcc;
|
||||
float kin, kdc, kbt, kba, kpf, kzu;
|
||||
float vin, vdc, vbt, vba, vpf, vzu;
|
||||
float tin, tdc, tbt, tba, tpf, tzu;
|
||||
float abt, aba, ain, ahx;
|
||||
float uus, uba, uin, udc;
|
||||
|
||||
byte cmd = 0x00;
|
||||
byte ext = 0x00;
|
||||
byte sum = 0x00;
|
||||
|
||||
unsigned long lastCommandTime = 0;
|
||||
byte autoResponse = 0x00;
|
||||
|
||||
byte byteResponse = 0x00;
|
||||
boolean needByte = false;
|
||||
boolean needSumm = false;
|
||||
|
||||
float floatResponse = 0.0;
|
||||
boolean needFloat = false;
|
||||
byte floatByte = 0;
|
||||
|
||||
unsigned long bt_time, ba_time;
|
||||
boolean bt_blocked = false, ba_blocked = false;
|
||||
|
||||
byte ba_full_count = 0, bt_full_count = 0;
|
||||
|
||||
unsigned long inc_time;
|
||||
|
||||
boolean vin_ok = false;
|
||||
byte vin_count = 0;
|
||||
|
||||
boolean vdc_ok = false;
|
||||
byte vdc_count = 0;
|
||||
|
||||
boolean vbt_ok = false, vbt_fail = false;
|
||||
byte vbt_count = 0, vbt_fail_count = 0;
|
||||
|
||||
boolean vba_ok = false;
|
||||
byte vba_count = 0;
|
||||
|
||||
boolean vpf_ok = false;
|
||||
byte vpf_count = 0;
|
||||
|
||||
boolean vzu_ok = false;
|
||||
byte vzu_count = 0;
|
||||
|
||||
boolean vcc_ok = false;
|
||||
byte vcc_count = 0;
|
||||
|
||||
boolean abt_ok = false;
|
||||
byte abt_count = 0;
|
||||
|
||||
boolean aba_ok = false;
|
||||
byte aba_count = 0;
|
||||
|
||||
boolean ain_ok = false;
|
||||
byte ain_count = 0;
|
||||
|
||||
boolean ahx_ok = false;
|
||||
byte ahx_count = 0;
|
||||
|
||||
boolean ba_enabled = false;
|
||||
boolean bt_enabled = true;
|
||||
boolean mv_enabled = false;
|
||||
boolean us_enabled = true;
|
||||
|
||||
boolean bt_full = false;
|
||||
boolean bt_charge = false;
|
||||
boolean ba_full = false;
|
||||
boolean ba_charge = false;
|
||||
|
||||
byte status_1 = 0x00;
|
||||
byte status_2 = 0x00;
|
||||
byte status_3 = 0x00;
|
||||
|
||||
/****************************************************************************
|
||||
* Главная программа
|
||||
****************************************************************************/
|
||||
|
||||
void setup() {
|
||||
if (DEBUG) {
|
||||
Serial.begin(9600);
|
||||
Serial.println("---");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// определение опорного напряжения
|
||||
analogReference(DEFAULT); // DEFAULT INTERNAL использовать vcc как AREF
|
||||
|
||||
kin = r1_2 / (r1_1 + r1_2);
|
||||
kdc = r2_2 / (r2_1 + r2_2);
|
||||
kbt = r3_2 / (r3_1 + r3_2);
|
||||
kba = r4_2 / (r4_1 + r4_2);
|
||||
kpf = r5_2 / (r5_1 + r5_2);
|
||||
kzu = r6_2 / (r6_1 + r6_2);
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc= ");
|
||||
Serial.println(vcc);
|
||||
Serial.println("---");
|
||||
}
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
pinMode(R_BT, OUTPUT);
|
||||
pinMode(R_BA, OUTPUT);
|
||||
pinMode(R_MV, OUTPUT);
|
||||
pinMode(R_US, OUTPUT);
|
||||
|
||||
pinMode(VIN_PIN, INPUT);
|
||||
pinMode(VDC_PIN, INPUT);
|
||||
pinMode(VBT_PIN, INPUT);
|
||||
pinMode(VBA_PIN, INPUT);
|
||||
pinMode(VPF_PIN, INPUT);
|
||||
pinMode(VZU_PIN, INPUT);
|
||||
|
||||
pinMode(ABT_PIN, INPUT);
|
||||
pinMode(ABA_PIN, INPUT);
|
||||
pinMode(AIN_PIN, INPUT);
|
||||
pinMode(AHX_PIN, INPUT);
|
||||
|
||||
pinMode(INC_PIN, INPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
bt_time = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Timeout protection
|
||||
if ((lastCommandTime + TIMEOUT < millis())) {
|
||||
floatResponse = 0.0;
|
||||
floatByte = 0;
|
||||
needFloat = false;
|
||||
autoResponse = TMO_RSP;
|
||||
}
|
||||
|
||||
// BLOCK OF MAGIC
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
readvcc();
|
||||
analogRead(VIN_PIN);
|
||||
// MAGIC
|
||||
|
||||
// Get voltages
|
||||
tin = 0.0;
|
||||
tdc = 0.0;
|
||||
tbt = 0.0;
|
||||
tba = 0.0;
|
||||
tpf = 0.0;
|
||||
tzu = 0.0;
|
||||
|
||||
tin += readvcc() * analogRead(VIN_PIN);
|
||||
tdc += readvcc() * analogRead(VDC_PIN);
|
||||
tbt += readvcc() * analogRead(VBT_PIN);
|
||||
tba += readvcc() * analogRead(VBA_PIN);
|
||||
tpf += readvcc() * analogRead(VPF_PIN);
|
||||
tzu += readvcc() * analogRead(VZU_PIN);
|
||||
|
||||
tcc = readvcc();
|
||||
tin = tin / 1024.0 / kin;// / REP_COUNT;
|
||||
tdc = tdc / 1024.0 / kdc;// / REP_COUNT;
|
||||
tbt = tbt / 1024.0 / kbt;// / REP_COUNT;
|
||||
tba = tba / 1024.0 / kba;// / REP_COUNT;
|
||||
tpf = tpf / 1024.0 / kpf;// / REP_COUNT;
|
||||
tzu = tzu / 1024.0 / kzu;// / REP_COUNT;
|
||||
|
||||
if (tcc > VCC_MIN) vcc = tcc;
|
||||
vin = tin;
|
||||
vdc = tdc;
|
||||
vbt = tbt;
|
||||
vba = tba;
|
||||
vpf = tpf;
|
||||
vzu = tzu;
|
||||
|
||||
// Get currents
|
||||
abt = (analogRead(ABT_PIN) - 512) * 0.0264;
|
||||
//if (abt < 0) abt *= -1;
|
||||
aba = (analogRead(ABA_PIN) - 512) * 0.0264;
|
||||
//if (aba < 0) aba *= -1;
|
||||
ain = (analogRead(AIN_PIN) - 512) * 0.0264;
|
||||
//if (ain < 0) ain *= -1;
|
||||
ahx = (analogRead(AHX_PIN) - 512) * 0.0264;
|
||||
//if (ahx < 0) ahx *= -1;
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.print("Vcc: ");
|
||||
Serial.println(vcc);
|
||||
Serial.print("Vin: ");
|
||||
Serial.println(vin);
|
||||
Serial.print("Vdc: ");
|
||||
Serial.println(vdc);
|
||||
Serial.print("Vbt: ");
|
||||
Serial.println(vbt);
|
||||
Serial.print("Vba: ");
|
||||
Serial.println(vba);
|
||||
Serial.print("Vpf: ");
|
||||
Serial.println(vpf);
|
||||
Serial.print("Vzu: ");
|
||||
Serial.println(vzu);
|
||||
Serial.println("---");
|
||||
}
|
||||
|
||||
// Vin check
|
||||
if (vin >= VIN_MIN && vin <= VIN_MAX) {
|
||||
if (! vin_ok) vin_count++;
|
||||
}
|
||||
else {
|
||||
vin_count = 0;
|
||||
vin_ok = false;
|
||||
}
|
||||
|
||||
if (vin_count >= V_CHECK_CYCLES) vin_ok = true;
|
||||
|
||||
// Vdc check
|
||||
if (vdc >= VDC_MIN && vdc <= VDC_MAX) {
|
||||
if (! vdc_ok) vdc_count++;
|
||||
}
|
||||
else {
|
||||
vdc_count = 0;
|
||||
vdc_ok = false;
|
||||
}
|
||||
|
||||
if (vdc_count >= V_CHECK_CYCLES) vdc_ok = true;
|
||||
|
||||
// Vbt check
|
||||
if (vbt >= VBT_MIN && vbt <= VBT_MAX) {
|
||||
if (! vbt_ok) vbt_count++;
|
||||
}
|
||||
else {
|
||||
vbt_count = 0;
|
||||
vbt_ok = false;
|
||||
}
|
||||
|
||||
if (vbt_count >= V_CHECK_CYCLES) vbt_ok = true;
|
||||
|
||||
// Vba check
|
||||
if (vba >= VBA_MIN && vba <= VBA_MAX) {
|
||||
if (! vba_ok) vba_count++;
|
||||
}
|
||||
else {
|
||||
vba_count = 0;
|
||||
vba_ok = false;
|
||||
}
|
||||
|
||||
if (vba_count >= V_CHECK_CYCLES) vba_ok = true;
|
||||
|
||||
// Vpf check
|
||||
if (vpf >= VPF_MIN && vpf <= VPF_MAX) {
|
||||
if (! vpf_ok) vpf_count++;
|
||||
}
|
||||
else {
|
||||
vpf_count = 0;
|
||||
vpf_ok = false;
|
||||
}
|
||||
|
||||
if (vpf_count >= V_CHECK_CYCLES) vpf_ok = true;
|
||||
|
||||
// Vzu check
|
||||
if (vzu >= VZU_MIN && vzu <= VZU_MAX) {
|
||||
if (! vzu_ok) vzu_count++;
|
||||
}
|
||||
else {
|
||||
vzu_count = 0;
|
||||
vzu_ok = false;
|
||||
}
|
||||
|
||||
if (vzu_count >= V_CHECK_CYCLES) vzu_ok = true;
|
||||
|
||||
// Vcc check
|
||||
if (vcc >= VCC_MIN && vcc <= VCC_MAX) {
|
||||
if (! vcc_ok) vcc_count++;
|
||||
}
|
||||
else {
|
||||
vcc_count = 0;
|
||||
vcc_ok = false;
|
||||
}
|
||||
|
||||
if (vcc_count >= V_CHECK_CYCLES) vcc_ok = true;
|
||||
|
||||
// Abt check
|
||||
if (abt >= ABT_MIN && abt <= ABT_MAX) {
|
||||
if (! abt_ok) abt_count++;
|
||||
}
|
||||
else {
|
||||
abt_count = 0;
|
||||
abt_ok = false;
|
||||
}
|
||||
|
||||
if (abt_count >= V_CHECK_CYCLES) abt_ok = true;
|
||||
|
||||
// Aba check
|
||||
if (aba >= ABA_MIN && aba <= ABA_MAX) {
|
||||
if (! aba_ok) aba_count++;
|
||||
}
|
||||
else {
|
||||
aba_count = 0;
|
||||
aba_ok = false;
|
||||
}
|
||||
|
||||
if (aba_count >= V_CHECK_CYCLES) aba_ok = true;
|
||||
|
||||
// Ain check
|
||||
if (ain >= AIN_MIN && ain <= AIN_MAX) {
|
||||
if (! ain_ok) ain_count++;
|
||||
}
|
||||
else {
|
||||
ain_count = 0;
|
||||
ain_ok = false;
|
||||
}
|
||||
|
||||
if (ain_count >= V_CHECK_CYCLES) ain_ok = true;
|
||||
|
||||
// Ahx check
|
||||
if (ahx >= AHX_MIN && ahx <= AHX_MAX) {
|
||||
if (! ahx_ok) ahx_count++;
|
||||
}
|
||||
else {
|
||||
ahx_count = 0;
|
||||
ahx_ok = false;
|
||||
}
|
||||
|
||||
if (ahx_count >= V_CHECK_CYCLES) ahx_ok = true;
|
||||
|
||||
// // BA full?
|
||||
// if (vba >= VBA_FULL) {
|
||||
// if (! ba_full && ! ba_enabled) ba_full_count++;
|
||||
// }
|
||||
// else {
|
||||
// ba_full_count = 0;
|
||||
// //ba_full = false;
|
||||
// }
|
||||
//
|
||||
// if (ba_full_count >= BA_FULL_CHECK_CYCLES) {
|
||||
// ba_full = true;
|
||||
// }
|
||||
//
|
||||
// if (ba_enabled && ! in_plugged()) {
|
||||
// ba_full = false;
|
||||
// }
|
||||
|
||||
// // Auto disable EX
|
||||
// if (! vdc_ok) { // || ((! vin_ok || ! in_plugged()) && ! ex_requested)) {
|
||||
// disableEX();
|
||||
// }
|
||||
//
|
||||
// // Disable EX block
|
||||
// if (ex_blocked && ex_time + EX_BLOCK_TIMEOUT < millis()) {
|
||||
// ex_blocked = false;
|
||||
// }
|
||||
//
|
||||
// // Auto enable EX
|
||||
// if (vdc_ok && ! ex_blocked) {
|
||||
// enableEX();
|
||||
// }
|
||||
//
|
||||
// // Auto enable BA (for charge)
|
||||
// if (! ba_enabled && vin_ok && in_plugged() && ! ba_full && ! ba_blocked) {
|
||||
// enableBA();
|
||||
// }
|
||||
//
|
||||
// // Auto disable BA (if charge complete)
|
||||
// if (ba_enabled && ba_full && in_plugged()) { //(ba_full || ! in_plugged())) {
|
||||
// disableBA();
|
||||
// }
|
||||
//
|
||||
// // Auto enable BA (for support)
|
||||
// if (! ba_enabled && ! ba_blocked && (! vin_ok || ! in_plugged())) {
|
||||
// enableBA();
|
||||
// }
|
||||
//
|
||||
// // Auto disable BA (if discharged)
|
||||
// if (ba_enabled && ! in_plugged() && ! vba_ok) {
|
||||
// disableBA();
|
||||
// }
|
||||
//
|
||||
// // Disable BA block
|
||||
// if (ba_blocked && ba_time + BA_BLOCK_TIMEOUT < millis()) {
|
||||
// ba_blocked = false;
|
||||
// }
|
||||
|
||||
// Compile status
|
||||
status_1 = 0x00;
|
||||
if (vcc_ok) status_1 |= 0x01;
|
||||
if (vin_ok) status_1 |= 0x02;
|
||||
if (vdc_ok) status_1 |= 0x04;
|
||||
if (vbt_ok) status_1 |= 0x08;
|
||||
if (vba_ok) status_1 |= 0x10;
|
||||
if (bt_enabled) status_1 |= 0x20;
|
||||
if (ba_enabled) status_1 |= 0x40;
|
||||
if (in_plugged()) status_1 |= 0x80;
|
||||
|
||||
status_2 = 0x00;
|
||||
if (bt_blocked) status_2 |= 0x01;
|
||||
if (ba_blocked) status_2 |= 0x02;
|
||||
if (bt_full) status_2 |= 0x04;
|
||||
if (ba_full) status_2 |= 0x08;
|
||||
if (vpf_ok) status_2 |= 0x10;
|
||||
if (vzu_ok) status_2 |= 0x20;
|
||||
if (mv_enabled) status_2 |= 0x40;
|
||||
if (us_enabled) status_2 |= 0x80;
|
||||
|
||||
status_3 = 0x00;
|
||||
if (abt_ok) status_3 |= 0x01;
|
||||
if (aba_ok) status_3 |= 0x02;
|
||||
if (ain_ok) status_3 |= 0x04;
|
||||
if (ahx_ok) status_3 |= 0x08;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Функции
|
||||
****************************************************************************/
|
||||
|
||||
float readvcc() {
|
||||
byte i;
|
||||
float result = 0.0;
|
||||
float tmp = 0.0;
|
||||
|
||||
//for (i = 0; i < REP_COUNT; i++) {
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
//result = result + tmp;
|
||||
// delay(5);
|
||||
//}
|
||||
|
||||
//result = result / REP_COUNT;
|
||||
return tmp;//result;
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
ext = Wire.read();
|
||||
if (ext == EXT_COM && byteCount == 3) {
|
||||
cmd = 0x00;
|
||||
sum = 0x00;
|
||||
|
||||
if (Wire.available()) sum = Wire.read();
|
||||
if (Wire.available()) cmd = Wire.read();
|
||||
|
||||
if ((cmd ^ XOR_SEQ) != sum) {
|
||||
autoResponse = CSE_RSP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
autoResponse = ERR_RSP;
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process command
|
||||
switch (cmd) {
|
||||
case COM_GET_VIN:
|
||||
sendFloat(vin);
|
||||
break;
|
||||
case COM_GET_VDC:
|
||||
sendFloat(vdc);
|
||||
break;
|
||||
case COM_GET_VBT:
|
||||
sendFloat(vbt);
|
||||
break;
|
||||
case COM_GET_VBA:
|
||||
sendFloat(vba);
|
||||
break;
|
||||
case COM_GET_VPF:
|
||||
sendFloat(vpf);
|
||||
break;
|
||||
case COM_GET_VZU:
|
||||
sendFloat(vzu);
|
||||
break;
|
||||
case COM_GET_VCC:
|
||||
sendFloat(vcc);
|
||||
break;
|
||||
|
||||
case COM_GET_ABT:
|
||||
sendFloat(abt);
|
||||
break;
|
||||
case COM_GET_ABA:
|
||||
sendFloat(aba);
|
||||
break;
|
||||
case COM_GET_AIN:
|
||||
sendFloat(ain);
|
||||
break;
|
||||
case COM_GET_AHX:
|
||||
sendFloat(ahx);
|
||||
break;
|
||||
|
||||
case COM_GET_TEMP:
|
||||
sendFloat(getInternalTemp());
|
||||
break;
|
||||
case COM_GET_STAT1:
|
||||
sendByte(status_1);
|
||||
break;
|
||||
case COM_GET_STAT2:
|
||||
sendByte(status_2);
|
||||
break;
|
||||
case COM_GET_STAT3:
|
||||
sendByte(status_3);
|
||||
break;
|
||||
|
||||
case COM_ENABLE_BA:
|
||||
commandResponse(enableBA());
|
||||
break;
|
||||
case COM_DISABLE_BA:
|
||||
commandResponse(disableBA());
|
||||
break;
|
||||
|
||||
case COM_ENABLE_BT:
|
||||
commandResponse(enableBT());
|
||||
break;
|
||||
case COM_DISABLE_BT:
|
||||
commandResponse(disableBT());
|
||||
break;
|
||||
|
||||
case COM_ENABLE_MV:
|
||||
enableMV();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_MV:
|
||||
disableMV();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_ENABLE_US:
|
||||
enableUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_DISABLE_US:
|
||||
disableUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
case COM_RESET_US:
|
||||
resetUS();
|
||||
commandResponse();
|
||||
break;
|
||||
|
||||
default:
|
||||
autoResponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void commandResponse() {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = OK_RSP;
|
||||
}
|
||||
|
||||
void commandResponse(byte response) {
|
||||
lastCommandTime = millis();
|
||||
autoResponse = response;
|
||||
}
|
||||
|
||||
void sendByte(byte value) {
|
||||
lastCommandTime = millis();
|
||||
byteResponse = value;
|
||||
needSumm = false;
|
||||
needByte = true;
|
||||
}
|
||||
|
||||
void sendFloat(float value) {
|
||||
lastCommandTime = millis();
|
||||
floatResponse = value;
|
||||
floatByte = 0;
|
||||
needFloat = true;
|
||||
}
|
||||
|
||||
byte cSum(byte value) {
|
||||
return value ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
byte cSum(byte *data, byte dataSize) {
|
||||
byte tmp = 0x00;
|
||||
for (byte i = 0; i < dataSize; i++) {
|
||||
tmp = tmp ^ data[i];
|
||||
}
|
||||
return tmp ^ XOR_SEQ;
|
||||
}
|
||||
|
||||
void answer() {
|
||||
// Want float value?
|
||||
if (needFloat) {
|
||||
// Get access to the float as a byte-array:
|
||||
byte *data = (byte *) &floatResponse;
|
||||
|
||||
if (floatByte < sizeof(floatResponse)) {
|
||||
// Send byte
|
||||
Wire.write(data[floatByte]);
|
||||
floatByte++;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(data, sizeof(floatResponse)));
|
||||
needFloat = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want byte value?
|
||||
if (needByte) {
|
||||
if (!needSumm) {
|
||||
// Send byte
|
||||
Wire.write(byteResponse);
|
||||
needSumm = true;
|
||||
}
|
||||
else {
|
||||
// Send control sum
|
||||
Wire.write(cSum(byteResponse));
|
||||
needSumm = false;
|
||||
needByte = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Want something else?
|
||||
Wire.write(autoResponse);
|
||||
}
|
||||
}
|
||||
// Nothing more to send
|
||||
autoResponse = NO_RSP;
|
||||
}
|
||||
|
||||
byte enableBT() {
|
||||
if (vbt_ok) {
|
||||
digitalWrite(R_BT, LOW);
|
||||
bt_enabled = true;
|
||||
bt_blocked = false;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte disableBT() {
|
||||
if ((vin_ok && in_plugged()) || (vba_ok && ba_enabled)) {
|
||||
digitalWrite(R_BT, HIGH);
|
||||
bt_enabled = false;
|
||||
bt_time = millis();
|
||||
bt_blocked = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte enableBA() {
|
||||
if (vba_ok) {
|
||||
digitalWrite(R_BA, HIGH);
|
||||
ba_enabled = true;
|
||||
ba_blocked = false;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
byte disableBA() {
|
||||
if ((vin_ok && in_plugged()) || (vbt_ok && bt_enabled)) {
|
||||
digitalWrite(R_BA, LOW);
|
||||
ba_enabled = false;
|
||||
ba_time = millis();
|
||||
ba_blocked = true;
|
||||
|
||||
return OK_RSP;
|
||||
}
|
||||
else return BLK_RSP;
|
||||
}
|
||||
|
||||
void enableMV() {
|
||||
digitalWrite(R_MV, HIGH);
|
||||
mv_enabled = true;
|
||||
}
|
||||
|
||||
void disableMV() {
|
||||
digitalWrite(R_MV, LOW);
|
||||
mv_enabled = false;
|
||||
}
|
||||
|
||||
void enableUS() {
|
||||
digitalWrite(R_US, LOW);
|
||||
us_enabled = true;
|
||||
}
|
||||
|
||||
void disableUS() {
|
||||
digitalWrite(R_US, HIGH);
|
||||
us_enabled = false;
|
||||
}
|
||||
|
||||
void resetUS() {
|
||||
disableUS();
|
||||
delay(500);
|
||||
enableUS();
|
||||
}
|
||||
|
||||
// Get the internal temperature
|
||||
float getInternalTemp() {
|
||||
unsigned int wADC;
|
||||
float t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return(t);
|
||||
}
|
||||
|
||||
bool in_plugged() {
|
||||
if (digitalRead(INC_PIN) == HIGH) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
29
HXtools/RGBconverter.py
Normal file
29
HXtools/RGBconverter.py
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# MAIN PROGRAM
|
||||
def main():
|
||||
color = int(input("Type color 0xHHHHHH>"), 16)
|
||||
|
||||
r = color >> 16
|
||||
g = (color >> 8) & 0x0000FF
|
||||
b = color & 0x0000FF
|
||||
|
||||
r1 = int(r / 255 * 31)
|
||||
g1 = int(g / 255 * 63)
|
||||
b1 = int(b / 255 * 31)
|
||||
|
||||
color = r1 << 11
|
||||
color = color + (g1 << 5)
|
||||
color = color + b1
|
||||
|
||||
print('RED: 0x%X, %i' % (r, r1))
|
||||
print('GREEN: 0x%X, %i' % (g, g1))
|
||||
print('BLUE: 0x%X, %i' % (b, b1))
|
||||
print('COLOR: 0x%X' % color)
|
||||
|
||||
|
||||
|
||||
# MAIN PROGRAM
|
||||
if __name__ == "__main__":
|
||||
main()
|
6
HXtools/hxtools.nja
Normal file
6
HXtools/hxtools.nja
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"venv": "",
|
||||
"name": "HXtools",
|
||||
"license": "GNU General Public License v3",
|
||||
"description": ""
|
||||
}
|
643
REflex/REflex.ino
Normal file
643
REflex/REflex.ino
Normal file
@ -0,0 +1,643 @@
|
||||
/////////////////////////////////////////
|
||||
// HXbot REflex firmware /
|
||||
// EoF 2016 EoF@itphx.ru /
|
||||
/////////////////////////////////////////
|
||||
|
||||
#include <PowerFunctions.h>
|
||||
#include <Ultrasonic.h>
|
||||
#include <Wire.h>
|
||||
#include <Servo.h>
|
||||
|
||||
// DEBUG
|
||||
#define DEBUG 1
|
||||
|
||||
// DEFINE
|
||||
#define SLAVE_ADDRESS 0x04
|
||||
#define XOR_SEQ 0xFF
|
||||
#define EXT_COM 0xAA
|
||||
|
||||
//#define LED_PIN 13
|
||||
#define IRE_PIN 2
|
||||
#define IRR_PIN 3
|
||||
#define SV_PIN 13 // vertical
|
||||
#define SV_CENTER 150 // 0 - up (min. 60), 180 - down (max. 170)
|
||||
#define SH_PIN 12 //horisontal
|
||||
#define SH_CENTER 90 // 0 - right, 180 - left
|
||||
#define SERVO_DELAY 10 // time interval between servo moves
|
||||
#define ULTRASONIC_PIN 6
|
||||
#define DRIVE_CHANNEL 2
|
||||
#define TIMEOUT 5000
|
||||
#define HEAD_V_FLAG 0x31
|
||||
#define HEAD_H_FLAG 0x30
|
||||
// Front and rear servos
|
||||
#define SF_PIN 10 // front servo
|
||||
#define SF_CENTER 96
|
||||
#define SR_PIN 11 // rear servo
|
||||
#define SR_CENTER 93
|
||||
#define FR_STEP 2
|
||||
// IR distance sensors
|
||||
#define IRD_FRONT_PIN 0
|
||||
#define IRD_F_MAX 3.0
|
||||
#define IRA_FRONT_PIN 1
|
||||
#define IRA_F_MIN 1.0
|
||||
#define IRD_REAR_PIN 2
|
||||
#define IRD_R_MAX 3.0
|
||||
#define IRA_REAR_PIN 3
|
||||
#define IRA_R_MIN 1.0
|
||||
#define IR_REPEAT_COUNT 3
|
||||
|
||||
// COMMANDS
|
||||
// Util
|
||||
#define COM_PING 0x01
|
||||
#define COM_GET_TEMP 0x02
|
||||
#define COM_GET_DISTANCE 0x03
|
||||
|
||||
// Stop
|
||||
#define STOP 0x0F
|
||||
// Move
|
||||
#define MOVE_FLAG 0x04
|
||||
#define MOVE_FLOAT 0x10
|
||||
#define MOVE_FWD1 0x11
|
||||
#define MOVE_FWD2 0x12
|
||||
#define MOVE_FWD3 0x13
|
||||
#define MOVE_FWD4 0x14
|
||||
#define MOVE_FWD5 0x15
|
||||
#define MOVE_FWD6 0x16
|
||||
#define MOVE_FWD7 0x17
|
||||
#define MOVE_BREAK 0x18
|
||||
#define MOVE_REV7 0x19
|
||||
#define MOVE_REV6 0x1A
|
||||
#define MOVE_REV5 0x1B
|
||||
#define MOVE_REV4 0x1C
|
||||
#define MOVE_REV3 0x1D
|
||||
#define MOVE_REV2 0x1E
|
||||
#define MOVE_REV1 0x1F
|
||||
// Steering
|
||||
#define STEER_FLAG 0x05
|
||||
#define STEER_CENTER 0x20
|
||||
#define STEER_LEFT1 0x21
|
||||
#define STEER_LEFT2 0x22
|
||||
#define STEER_LEFT3 0x23
|
||||
#define STEER_LEFT4 0x24
|
||||
#define STEER_LEFT5 0x25
|
||||
#define STEER_LEFT6 0x26
|
||||
#define STEER_LEFT7 0x27
|
||||
#define STEER_FIX_CENTER 0x28
|
||||
#define STEER_RIGHT7 0x29
|
||||
#define STEER_RIGHT6 0x2A
|
||||
#define STEER_RIGHT5 0x2B
|
||||
#define STEER_RIGHT4 0x2C
|
||||
#define STEER_RIGHT3 0x2D
|
||||
#define STEER_RIGHT2 0x2E
|
||||
#define STEER_RIGHT1 0x2F
|
||||
|
||||
// Response
|
||||
#define OK_RSP 0x00
|
||||
#define NO_RSP 0xFF
|
||||
#define ERR_RSP 0x01
|
||||
#define BLK_RSP 0x02
|
||||
#define CSE_RSP 0x03
|
||||
#define IOE_RSP 0x04
|
||||
#define TMO_RSP 0x05
|
||||
|
||||
// VAR
|
||||
const float typVbg = 1.13; // 1.0 -- 1.2
|
||||
|
||||
float ird_f, ira_f, ird_r, ira_r;
|
||||
boolean ird_ignore = false, ira_ignore = false;
|
||||
|
||||
byte cmd = 0;
|
||||
byte flg = 0;
|
||||
byte ext = 0;
|
||||
|
||||
byte autoresponse = 0;
|
||||
long usDistance = 0;
|
||||
unsigned long lastCommandTime = 0;
|
||||
boolean isMove = false;
|
||||
boolean frBlock = false;
|
||||
|
||||
PowerFunctions pfDrive(IRE_PIN, DRIVE_CHANNEL);
|
||||
Ultrasonic usSensor(ULTRASONIC_PIN);
|
||||
Servo servV, servH, servF, servR;
|
||||
byte destV, destH;
|
||||
unsigned long lastServoMove = 0;
|
||||
|
||||
// SETUP
|
||||
void setup() {
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.println("GO!");
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
//pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
// Initialize i2c as slave
|
||||
Wire.begin(SLAVE_ADDRESS);
|
||||
|
||||
// Define callbacks for i2c communication
|
||||
Wire.onReceive(receiveData);
|
||||
Wire.onRequest(answer);
|
||||
|
||||
analogReference(DEFAULT);
|
||||
|
||||
destH = SH_CENTER;
|
||||
destV = SV_CENTER;
|
||||
|
||||
if (DEBUG) {
|
||||
Serial.println("Setup complete");
|
||||
}
|
||||
}
|
||||
|
||||
// MAIN LOOP
|
||||
void loop() {
|
||||
// Timeout protection
|
||||
if ((lastCommandTime + TIMEOUT < millis()) && isMove) {
|
||||
pfDrive.combo_pwm(PWM_BRK, PWM_BRK);
|
||||
servV.detach();
|
||||
servH.detach();
|
||||
isMove = false;
|
||||
autoresponse = TMO_RSP;
|
||||
}
|
||||
|
||||
moveServo();
|
||||
|
||||
//usDistance = usSensor.MeasureInCentimeters();
|
||||
if (DEBUG) {
|
||||
ird_f = analogRead(IRD_FRONT_PIN) * readvcc() / 1024;
|
||||
ira_f = analogRead(IRA_FRONT_PIN) * readvcc() / 1024;
|
||||
ird_r = analogRead(IRD_REAR_PIN) * readvcc() / 1024;
|
||||
ira_r = analogRead(IRA_REAR_PIN) * readvcc() / 1024;
|
||||
|
||||
Serial.print("VCC: ");
|
||||
Serial.println(readvcc());
|
||||
Serial.print("IRD_F: ");
|
||||
Serial.println(ird_f);
|
||||
Serial.print("IRA_F: ");
|
||||
Serial.println(ira_f);
|
||||
Serial.print("IRD_R: ");
|
||||
Serial.println(ird_r);
|
||||
Serial.print("IRA_R: ");
|
||||
Serial.println(ira_r);
|
||||
Serial.println("------");
|
||||
delay(1000);
|
||||
}
|
||||
//delay(100);
|
||||
}
|
||||
|
||||
void moveResponse(byte rsp = OK_RSP) {
|
||||
lastCommandTime = millis();
|
||||
isMove = true;
|
||||
autoresponse = rsp;
|
||||
}
|
||||
|
||||
// Callback for received data
|
||||
void receiveData(int byteCount) {
|
||||
|
||||
while(Wire.available()) {
|
||||
// Get command
|
||||
cmd = Wire.read();
|
||||
if (cmd == EXT_COM && byteCount == 3) {
|
||||
flg = 0x00;
|
||||
ext = 0x00;
|
||||
|
||||
if (Wire.available()) ext = Wire.read();
|
||||
if (Wire.available()) flg = Wire.read();
|
||||
}
|
||||
else {
|
||||
// Cleanup I2C bus
|
||||
while(Wire.available()) {
|
||||
ext = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case COM_PING:
|
||||
autoresponse = OK_RSP;
|
||||
break;
|
||||
case STOP:
|
||||
pfDrive.combo_pwm(PWM_BRK, PWM_BRK);
|
||||
moveResponse();
|
||||
break;
|
||||
case COM_GET_TEMP:
|
||||
autoresponse = getInternalTemp();
|
||||
break;
|
||||
case COM_GET_DISTANCE:
|
||||
usDistance = usSensor.MeasureInCentimeters();
|
||||
if (usDistance >= 255) {
|
||||
autoresponse = NO_RSP;
|
||||
} else {
|
||||
autoresponse = usDistance;
|
||||
}
|
||||
break;
|
||||
case EXT_COM:
|
||||
switch (flg) {
|
||||
case HEAD_V_FLAG: case HEAD_H_FLAG:
|
||||
headControl(flg, ext);
|
||||
break;
|
||||
case MOVE_FLAG: case STEER_FLAG:
|
||||
moveControl(flg, ext);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
autoresponse = ERR_RSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void headControl(byte flg, byte val) {
|
||||
if (! servV.attached()) servV.attach(SV_PIN);
|
||||
if (! servH.attached()) servH.attach(SH_PIN);
|
||||
|
||||
switch (flg) {
|
||||
case HEAD_V_FLAG:
|
||||
destV = val;
|
||||
break;
|
||||
case HEAD_H_FLAG:
|
||||
destH = val;
|
||||
break;
|
||||
}
|
||||
moveResponse();
|
||||
}
|
||||
|
||||
void moveServo() {
|
||||
byte curV, curH;
|
||||
|
||||
if (! isMove) return;
|
||||
|
||||
if (lastServoMove + SERVO_DELAY < millis()) {
|
||||
curV = servV.read();
|
||||
curH = servH.read();
|
||||
|
||||
if (destV < curV) servV.write(curV - 1);
|
||||
if (destV > curV) servV.write(curV + 1);
|
||||
if (destH < curH) servH.write(curH - 1);
|
||||
if (destH > curH) servH.write(curH + 1);
|
||||
|
||||
lastServoMove = millis();
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for sending data
|
||||
void answer() {
|
||||
Wire.write(autoresponse);
|
||||
}
|
||||
|
||||
boolean ird_f_ok() {
|
||||
if (! ird_ignore) {
|
||||
|
||||
ird_f = 0.0;
|
||||
|
||||
for (byte i = 0; i < IR_REPEAT_COUNT; i++) {
|
||||
ird_f = ird_f + analogRead(IRD_FRONT_PIN) * readvcc() / 1024;
|
||||
}
|
||||
ird_f = ird_f / IR_REPEAT_COUNT;
|
||||
|
||||
if (ird_f <= IRD_F_MAX) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else return true;
|
||||
}
|
||||
|
||||
boolean ird_r_ok() {
|
||||
if (! ird_ignore) {
|
||||
|
||||
ird_r = 0.0;
|
||||
|
||||
for (byte i = 0; i < IR_REPEAT_COUNT; i++) {
|
||||
ird_r = ird_r + analogRead(IRD_REAR_PIN) * readvcc() / 1024;
|
||||
}
|
||||
ird_r = ird_r / IR_REPEAT_COUNT;
|
||||
|
||||
if (ird_r <= IRD_R_MAX) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else return true;
|
||||
}
|
||||
|
||||
boolean ira_f_ok() {
|
||||
if (! ira_ignore) {
|
||||
|
||||
ira_f = 0.0;
|
||||
|
||||
for (byte i = 0; i < IR_REPEAT_COUNT; i++) {
|
||||
ira_f = ira_f + analogRead(IRA_FRONT_PIN) * readvcc() / 1024;
|
||||
}
|
||||
ira_f = ira_f / IR_REPEAT_COUNT;
|
||||
|
||||
if (ira_f >= IRA_F_MIN) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else return true;
|
||||
}
|
||||
|
||||
boolean ira_r_ok() {
|
||||
if (! ira_ignore) {
|
||||
|
||||
ira_r = 0.0;
|
||||
|
||||
for (byte i = 0; i < IR_REPEAT_COUNT; i++) {
|
||||
ira_r = ira_r + analogRead(IRA_REAR_PIN) * readvcc() / 1024;
|
||||
}
|
||||
ira_r = ira_r / IR_REPEAT_COUNT;
|
||||
|
||||
if (ira_r >= IRA_R_MIN) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else return true;
|
||||
}
|
||||
|
||||
void stopMove() {
|
||||
pfDrive.single_pwm(RED, PWM_BRK);
|
||||
pfDrive.single_pwm(RED, PWM_BRK);
|
||||
pfDrive.single_pwm(RED, PWM_BRK);
|
||||
}
|
||||
|
||||
void moveControl(byte flg, byte cmd) {
|
||||
if (flg == MOVE_FLAG) {
|
||||
if (cmd >= MOVE_FWD1 && cmd <= MOVE_FWD7) {
|
||||
if (! ira_f_ok()) {
|
||||
stopMove();
|
||||
moveResponse(BLK_RSP);
|
||||
return;
|
||||
}
|
||||
if (! ird_f_ok()) {
|
||||
stopMove();
|
||||
moveResponse(BLK_RSP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd >= MOVE_REV7 && cmd <= MOVE_REV1) {
|
||||
if (! ira_r_ok()) {
|
||||
stopMove();
|
||||
moveResponse(BLK_RSP);
|
||||
return;
|
||||
}
|
||||
if (! ird_r_ok()) {
|
||||
stopMove();
|
||||
moveResponse(BLK_RSP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
// Moving
|
||||
case MOVE_FLOAT:
|
||||
pfDrive.single_pwm(RED, PWM_FLT);
|
||||
break;
|
||||
case MOVE_FWD1:
|
||||
pfDrive.single_pwm(RED, PWM_FWD1);
|
||||
break;
|
||||
case MOVE_FWD2:
|
||||
pfDrive.single_pwm(RED, PWM_FWD2);
|
||||
break;
|
||||
case MOVE_FWD3:
|
||||
pfDrive.single_pwm(RED, PWM_FWD3);
|
||||
break;
|
||||
case MOVE_FWD4:
|
||||
pfDrive.single_pwm(RED, PWM_FWD4);
|
||||
break;
|
||||
case MOVE_FWD5:
|
||||
pfDrive.single_pwm(RED, PWM_FWD5);
|
||||
break;
|
||||
case MOVE_FWD6:
|
||||
pfDrive.single_pwm(RED, PWM_FWD6);
|
||||
break;
|
||||
case MOVE_FWD7:
|
||||
pfDrive.single_pwm(RED, PWM_FWD7);
|
||||
break;
|
||||
case MOVE_BREAK:
|
||||
pfDrive.single_pwm(RED, PWM_BRK);
|
||||
break;
|
||||
case MOVE_REV1:
|
||||
pfDrive.single_pwm(RED, PWM_REV1);
|
||||
break;
|
||||
case MOVE_REV2:
|
||||
pfDrive.single_pwm(RED, PWM_REV2);
|
||||
break;
|
||||
case MOVE_REV3:
|
||||
pfDrive.single_pwm(RED, PWM_REV3);
|
||||
break;
|
||||
case MOVE_REV4:
|
||||
pfDrive.single_pwm(RED, PWM_REV4);
|
||||
break;
|
||||
case MOVE_REV5:
|
||||
pfDrive.single_pwm(RED, PWM_REV5);
|
||||
break;
|
||||
case MOVE_REV6:
|
||||
pfDrive.single_pwm(RED, PWM_REV6);
|
||||
break;
|
||||
case MOVE_REV7:
|
||||
pfDrive.single_pwm(RED, PWM_REV7);
|
||||
break;
|
||||
|
||||
// Steering
|
||||
case STEER_CENTER:
|
||||
pfDrive.single_pwm(BLUE, PWM_FLT);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT1:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD1);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT2:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD2);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT3:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD3);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT4:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD4);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT5:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD5);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT6:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD6);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_LEFT7:
|
||||
pfDrive.single_pwm(BLUE, PWM_FWD7);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_FIX_CENTER:
|
||||
pfDrive.single_pwm(BLUE, PWM_BRK);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT1:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV1);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT2:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV2);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT3:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV3);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT4:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV4);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT5:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV5);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT6:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV6);
|
||||
frControl(cmd);
|
||||
break;
|
||||
case STEER_RIGHT7:
|
||||
pfDrive.single_pwm(BLUE, PWM_REV7);
|
||||
frControl(cmd);
|
||||
break;
|
||||
default:
|
||||
moveResponse(NO_RSP);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
// Send response
|
||||
moveResponse();
|
||||
}
|
||||
|
||||
void frControl(byte cmd) {
|
||||
if (! frBlock) {
|
||||
if (! servF.attached()) servF.attach(SF_PIN);
|
||||
if (! servR.attached()) servR.attach(SR_PIN);
|
||||
|
||||
switch (cmd) {
|
||||
case STEER_CENTER:
|
||||
servF.write(SF_CENTER);
|
||||
servR.write(SR_CENTER);
|
||||
break;
|
||||
case STEER_LEFT1:
|
||||
servF.write(SF_CENTER - FR_STEP * 1);
|
||||
servR.write(SR_CENTER + FR_STEP * 1);
|
||||
break;
|
||||
case STEER_LEFT2:
|
||||
servF.write(SF_CENTER - FR_STEP * 2);
|
||||
servR.write(SR_CENTER + FR_STEP * 2);
|
||||
break;
|
||||
case STEER_LEFT3:
|
||||
servF.write(SF_CENTER - FR_STEP * 3);
|
||||
servR.write(SR_CENTER + FR_STEP * 3);
|
||||
break;
|
||||
case STEER_LEFT4:
|
||||
servF.write(SF_CENTER - FR_STEP * 4);
|
||||
servR.write(SR_CENTER + FR_STEP * 4);
|
||||
break;
|
||||
case STEER_LEFT5:
|
||||
servF.write(SF_CENTER - FR_STEP * 5);
|
||||
servR.write(SR_CENTER + FR_STEP * 5);
|
||||
break;
|
||||
case STEER_LEFT6:
|
||||
servF.write(SF_CENTER - FR_STEP * 6);
|
||||
servR.write(SR_CENTER + FR_STEP * 6);
|
||||
break;
|
||||
case STEER_LEFT7:
|
||||
servF.write(SF_CENTER - FR_STEP * 7);
|
||||
servR.write(SR_CENTER + FR_STEP * 7);
|
||||
break;
|
||||
case STEER_FIX_CENTER:
|
||||
servF.write(SF_CENTER);
|
||||
servR.write(SR_CENTER);
|
||||
break;
|
||||
case STEER_RIGHT1:
|
||||
servF.write(SF_CENTER + FR_STEP * 1);
|
||||
servR.write(SR_CENTER - FR_STEP * 1);
|
||||
break;
|
||||
case STEER_RIGHT2:
|
||||
servF.write(SF_CENTER + FR_STEP * 2);
|
||||
servR.write(SR_CENTER - FR_STEP * 2);
|
||||
break;
|
||||
case STEER_RIGHT3:
|
||||
servF.write(SF_CENTER + FR_STEP * 3);
|
||||
servR.write(SR_CENTER - FR_STEP * 3);
|
||||
break;
|
||||
case STEER_RIGHT4:
|
||||
servF.write(SF_CENTER + FR_STEP * 4);
|
||||
servR.write(SR_CENTER - FR_STEP * 4);
|
||||
break;
|
||||
case STEER_RIGHT5:
|
||||
servF.write(SF_CENTER + FR_STEP * 5);
|
||||
servR.write(SR_CENTER - FR_STEP * 5);
|
||||
break;
|
||||
case STEER_RIGHT6:
|
||||
servF.write(SF_CENTER + FR_STEP * 6);
|
||||
servR.write(SR_CENTER - FR_STEP * 6);
|
||||
break;
|
||||
case STEER_RIGHT7:
|
||||
servF.write(SF_CENTER + FR_STEP * 7);
|
||||
servR.write(SR_CENTER - FR_STEP * 7);
|
||||
break;
|
||||
default:
|
||||
servF.write(SF_CENTER);
|
||||
servR.write(SR_CENTER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the internal temperature of the arduino
|
||||
double getInternalTemp(void) {
|
||||
unsigned int wADC;
|
||||
double t;
|
||||
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
|
||||
ADCSRA |= _BV(ADEN); // enable the ADC
|
||||
delay(20); // wait for voltages to become stable.
|
||||
ADCSRA |= _BV(ADSC); // Start the ADC
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
wADC = ADCW;
|
||||
t = (wADC - 324.31 ) / 1.22;
|
||||
return (t);
|
||||
}
|
||||
|
||||
float readvcc() {
|
||||
float tmp = 0.0;
|
||||
|
||||
// Read 1.1V reference against Avcc
|
||||
// set the reference to vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
// works on an Arduino 168 or 328
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(3); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA,ADSC)); // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
tmp = (high<<8) | low;
|
||||
tmp = (typVbg * 1023.0) / tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
28
reset-hxlcd
Executable file
28
reset-hxlcd
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# You need to have installed Wiring Pi library to be able
|
||||
# to use this script
|
||||
# see http://wiringpi.com/download-and-install/
|
||||
|
||||
# define GPIO number where RESET line (DTR) is connected to
|
||||
# here GPIO 18
|
||||
io=24
|
||||
|
||||
# Set IO pin to output
|
||||
gpio -g mode $io out
|
||||
|
||||
# Set IO pin to LOW (bring reset to GND)
|
||||
echo -n "Resetting with GPIO"$io"..."
|
||||
|
||||
gpio -g write $io 0
|
||||
|
||||
# wait little time
|
||||
sleep 1
|
||||
|
||||
# Set IO pin to HIGH (release reset to VDD)
|
||||
gpio -g write $io 1
|
||||
echo "done"
|
||||
|
||||
# Optionnal, you can just after reset launch a
|
||||
# serial connection to Arduino
|
||||
# uncomment the following line to do it
|
||||
#picocom -b 115200 --imap lfcrlf /dev/ttyS0
|
27
reset-hxpower
Executable file
27
reset-hxpower
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
# You need to have installed Wiring Pi library to be able
|
||||
# to use this script
|
||||
# see http://wiringpi.com/download-and-install/
|
||||
|
||||
# define GPIO number where RESET line (DTR) is connected to
|
||||
# here GPIO 18
|
||||
io=25
|
||||
|
||||
# Set IO pin to output
|
||||
gpio -g mode $io out
|
||||
|
||||
# Set IO pin to LOW (bring reset to GND)
|
||||
echo -n "Resetting with GPIO"$io"..."
|
||||
gpio -g write $io 0
|
||||
|
||||
# wait little time
|
||||
sleep 1
|
||||
|
||||
# Set IO pin to HIGH (release reset to VDD)
|
||||
gpio -g write $io 1
|
||||
echo "done"
|
||||
|
||||
# Optionnal, you can just after reset launch a
|
||||
# serial connection to Arduino
|
||||
# uncomment the following line to do it
|
||||
#picocom -b 115200 --imap lfcrlf /dev/ttyS0
|
27
reset-reflex
Executable file
27
reset-reflex
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
# You need to have installed Wiring Pi library to be able
|
||||
# to use this script
|
||||
# see http://wiringpi.com/download-and-install/
|
||||
|
||||
# define GPIO number where RESET line (DTR) is connected to
|
||||
# here GPIO 18
|
||||
io=18
|
||||
|
||||
# Set IO pin to output
|
||||
gpio -g mode $io out
|
||||
|
||||
# Set IO pin to LOW (bring reset to GND)
|
||||
echo -n "Resetting with GPIO"$io"..."
|
||||
gpio -g write $io 0
|
||||
|
||||
# wait little time
|
||||
sleep 1
|
||||
|
||||
# Set IO pin to HIGH (release reset to VDD)
|
||||
gpio -g write $io 1
|
||||
echo "done"
|
||||
|
||||
# Optionnal, you can just after reset launch a
|
||||
# serial connection to Arduino
|
||||
# uncomment the following line to do it
|
||||
#picocom -b 115200 --imap lfcrlf /dev/ttyS0
|
Loading…
Reference in New Issue
Block a user