Наработки за 5 лет
This commit is contained in:
Binary file not shown.
Binary file not shown.
+1650
File diff suppressed because it is too large
Load Diff
Executable
+366
@@ -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$'
|
||||
Executable
+711
@@ -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()
|
||||
Executable
+257
@@ -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()
|
||||
Executable
+132
@@ -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()
|
||||
Executable
+234
@@ -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)
|
||||
Executable
+149
@@ -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
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
Executable
+587
@@ -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
|
||||
Executable
+171
@@ -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
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
Executable
+224
@@ -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)
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
+29
@@ -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"
|
||||
}
|
||||
Executable
+4
@@ -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}'
|
||||
Executable
+19
@@ -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
|
||||
Executable
+5
@@ -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
|
||||
Executable
+368
@@ -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$'
|
||||
Binary file not shown.
Executable
+724
@@ -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()
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"venv": "",
|
||||
"project-type": "Import from sources",
|
||||
"name": "HXgui",
|
||||
"license": "GNU General Public License v3",
|
||||
"description": "HXbot GUI"
|
||||
}
|
||||
+339
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
// }
|
||||
}
|
||||
|
||||
Executable
+824
@@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"venv": "",
|
||||
"name": "HXtools",
|
||||
"license": "GNU General Public License v3",
|
||||
"description": ""
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Executable
+28
@@ -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
|
||||
Executable
+27
@@ -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
|
||||
Executable
+27
@@ -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
|
||||
Reference in New Issue
Block a user