mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-14 18:46:59 +00:00
420 lines
14 KiB
Python
420 lines
14 KiB
Python
# -*- coding: utf-8 -*
|
|
'''!
|
|
@file DFRobot_GP8403.py
|
|
@brief This is a function library of the DAC module.
|
|
@copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
|
|
@license The MIT License (MIT)
|
|
@author [tangjie](jie.tang@dfrobot.com)
|
|
@version V1.0
|
|
@date 2022-03-03
|
|
@url https://github.com/DFRobot/DFRobot_GP8403
|
|
'''
|
|
from __future__ import print_function
|
|
import sys
|
|
import smbus
|
|
import time
|
|
import datetime
|
|
import RPi.GPIO as GPIO
|
|
|
|
|
|
FullSine5Bit = [
|
|
2048,2447,2831,3185,3495,3750,3939,4056,
|
|
4095,4056,3939,3750,3495,3185,2831,2447,
|
|
2048,1648,1264, 910, 600, 345, 156, 39,
|
|
0, 39, 156, 345, 600, 910,1264,1648]
|
|
|
|
FullSine6Bit = [
|
|
2048, 2248, 2447, 2642, 2831, 3013, 3185, 3346,
|
|
3495, 3630, 3750, 3853, 3939, 4007, 4056, 4085,
|
|
4095, 4085, 4056, 4007, 3939, 3853, 3750, 3630,
|
|
3495, 3346, 3185, 3013, 2831, 2642, 2447, 2248,
|
|
2048, 1847, 1648, 1453, 1264, 1082, 910, 749,
|
|
600, 465, 345, 242, 156, 88, 39, 10,
|
|
0, 10, 39, 88, 156, 242, 345, 465,
|
|
600, 749, 910, 1082, 1264, 1453, 1648, 1847]
|
|
|
|
FullSine7Bit = [
|
|
2048, 2148, 2248, 2348, 2447, 2545, 2642, 2737,
|
|
2831, 2923, 3013, 3100, 3185, 3267, 3346, 3423,
|
|
3495, 3565, 3630, 3692, 3750, 3804, 3853, 3898,
|
|
3939, 3975, 4007, 4034, 4056, 4073, 4085, 4093,
|
|
4095, 4093, 4085, 4073, 4056, 4034, 4007, 3975,
|
|
3939, 3898, 3853, 3804, 3750, 3692, 3630, 3565,
|
|
3495, 3423, 3346, 3267, 3185, 3100, 3013, 2923,
|
|
2831, 2737, 2642, 2545, 2447, 2348, 2248, 2148,
|
|
2048, 1947, 1847, 1747, 1648, 1550, 1453, 1358,
|
|
1264, 1172, 1082, 995, 910, 828, 749, 672,
|
|
600, 530, 465, 403, 345, 291, 242, 197,
|
|
156, 120, 88, 61, 39, 22, 10, 2,
|
|
0, 2, 10, 22, 39, 61, 88, 120,
|
|
156, 197, 242, 291, 345, 403, 465, 530,
|
|
600, 672, 749, 828, 910, 995, 1082, 1172,
|
|
1264, 1358, 1453, 1550, 1648, 1747, 1847, 1947]
|
|
|
|
FullSine8Bit = [
|
|
2048, 2098, 2148, 2198, 2248, 2298, 2348, 2398,
|
|
2447, 2496, 2545, 2594, 2642, 2690, 2737, 2784,
|
|
2831, 2877, 2923, 2968, 3013, 3057, 3100, 3143,
|
|
3185, 3226, 3267, 3307, 3346, 3385, 3423, 3459,
|
|
3495, 3530, 3565, 3598, 3630, 3662, 3692, 3722,
|
|
3750, 3777, 3804, 3829, 3853, 3876, 3898, 3919,
|
|
3939, 3958, 3975, 3992, 4007, 4021, 4034, 4045,
|
|
4056, 4065, 4073, 4080, 4085, 4089, 4093, 4094,
|
|
4095, 4094, 4093, 4089, 4085, 4080, 4073, 4065,
|
|
4056, 4045, 4034, 4021, 4007, 3992, 3975, 3958,
|
|
3939, 3919, 3898, 3876, 3853, 3829, 3804, 3777,
|
|
3750, 3722, 3692, 3662, 3630, 3598, 3565, 3530,
|
|
3495, 3459, 3423, 3385, 3346, 3307, 3267, 3226,
|
|
3185, 3143, 3100, 3057, 3013, 2968, 2923, 2877,
|
|
2831, 2784, 2737, 2690, 2642, 2594, 2545, 2496,
|
|
2447, 2398, 2348, 2298, 2248, 2198, 2148, 2098,
|
|
2048, 1997, 1947, 1897, 1847, 1797, 1747, 1697,
|
|
1648, 1599, 1550, 1501, 1453, 1405, 1358, 1311,
|
|
1264, 1218, 1172, 1127, 1082, 1038, 995, 952,
|
|
910, 869, 828, 788, 749, 710, 672, 636,
|
|
600, 565, 530, 497, 465, 433, 403, 373,
|
|
345, 318, 291, 266, 242, 219, 197, 176,
|
|
156, 137, 120, 103, 88, 74, 61, 50,
|
|
39, 30, 22, 15, 10, 6, 2, 1,
|
|
0, 1, 2, 6, 10, 15, 22, 30,
|
|
39, 50, 61, 74, 88, 103, 120, 137,
|
|
156, 176, 197, 219, 242, 266, 291, 318,
|
|
345, 373, 403, 433, 465, 497, 530, 565,
|
|
600, 636, 672, 710, 749, 788, 828, 869,
|
|
910, 952, 995, 1038, 1082, 1127, 1172, 1218,
|
|
1264, 1311, 1358, 1405, 1453, 1501, 1550, 1599,
|
|
1648, 1697, 1747, 1797, 1847, 1897, 1947, 1997]
|
|
|
|
|
|
##Select DAC output voltage of 0-5V
|
|
OUTPUT_RANGE_5V = 0
|
|
##Select DAC output voltage of 0-10V
|
|
OUTPUT_RANGE_10V = 17
|
|
##Select to output from channel 0
|
|
CHANNEL0 = 1
|
|
##Select to output from channel 1
|
|
CHANNEL1 = 2
|
|
##Select to output from all the channels
|
|
CHANNELALL = 3
|
|
|
|
class DFRobot_GP8403():
|
|
## Configure current sensor register
|
|
GP8403_CONFIG_CURRENT_REG = 0x02
|
|
## Store function timing start head
|
|
GP8302_STORE_TIMING_HEAD = 0x02
|
|
## The first address for entering store timing
|
|
GP8302_STORE_TIMING_ADDR = 0x10
|
|
## The command 1 to enter store timing
|
|
GP8302_STORE_TIMING_CMD1 = 0x03
|
|
## The command 2 to enter store timing
|
|
GP8302_STORE_TIMING_CMD2 = 0x00
|
|
## Total I2C communication cycle 5us
|
|
I2C_CYCLE_TOTAL = 0.000005
|
|
## The first half cycle of the total I2C communication cycle 2us
|
|
I2C_CYCLE_BEFORE = 0.000002
|
|
## The second half cycle of the total I2C communication cycle 3us
|
|
I2C_CYCLE_AFTER = 0.000003
|
|
|
|
# Store procedure interval delay time: 10ms (1000us)
|
|
# (should be more than 7ms according to spec)
|
|
GP8302_STORE_TIMING_DELAY = 0.0000010
|
|
|
|
|
|
def __init__(self,addr):
|
|
self._addr = addr
|
|
self.outPutSetRange = 0x01
|
|
self.voltage = 5000
|
|
self._scl = 3
|
|
self._sda = 2
|
|
self.dataTransmission = 0
|
|
GPIO.setmode(GPIO.BCM)
|
|
GPIO.setwarnings(False)
|
|
self.i2c = smbus.SMBus(1)
|
|
|
|
|
|
def begin(self):
|
|
'''!
|
|
@param Initialize the sensor
|
|
'''
|
|
if(self.i2c.read_byte(self._addr) != 0):
|
|
return 0
|
|
return 1
|
|
|
|
def set_DAC_outrange(self,mode):
|
|
'''!
|
|
@brief Set DAC output range
|
|
@param mode Select DAC output range
|
|
'''
|
|
if mode == OUTPUT_RANGE_5V:
|
|
self.voltage = 5000
|
|
elif mode == OUTPUT_RANGE_10V :
|
|
self.voltage = 10000
|
|
self.i2c.write_word_data(self._addr,self.outPutSetRange,mode)
|
|
|
|
def set_DAC_out_voltage(self,data,channel):
|
|
'''!
|
|
@brief Select DAC output channel & range
|
|
@param data Set output data
|
|
@param channel Set output channel
|
|
'''
|
|
self.dataTransmission = ((float(data) / self.voltage) * 4095)
|
|
self.dataTransmission = int(self.dataTransmission) << 4
|
|
self._send_data(self.dataTransmission,channel)
|
|
|
|
def store(self):
|
|
'''!
|
|
@brief Save the present current config, after the config is saved successfully, it will be enabled when the module is powered down and restarts
|
|
'''
|
|
self._start_signal()
|
|
self._send_byte(self.GP8302_STORE_TIMING_HEAD, 0, 3, False)
|
|
self._stop_signal()
|
|
self._start_signal()
|
|
self._send_byte(self.GP8302_STORE_TIMING_ADDR)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD1)
|
|
self._stop_signal()
|
|
|
|
self._start_signal()
|
|
self._send_byte(self._addr<<1, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2, 1)
|
|
self._stop_signal()
|
|
|
|
time.sleep(self.GP8302_STORE_TIMING_DELAY)
|
|
|
|
self._start_signal()
|
|
self._send_byte(self.GP8302_STORE_TIMING_HEAD, 0, 3, False)
|
|
self._stop_signal()
|
|
self._start_signal()
|
|
self._send_byte(self.GP8302_STORE_TIMING_ADDR)
|
|
self._send_byte(self.GP8302_STORE_TIMING_CMD2)
|
|
self._stop_signal()
|
|
|
|
|
|
def output_sin(self,amp,freq,offset,channel):
|
|
'''!
|
|
@brief Set the sensor outputs sine wave
|
|
@param amp Set sine wave amplitude Vp
|
|
@param freq Set sine wave frequency f
|
|
@param offset Set sine wave DC offset Voffset
|
|
@param channel Output channel. 0: channel 0; 1: channel 1; 2: all the channels
|
|
'''
|
|
if(freq < 6):
|
|
num = 256
|
|
elif( 6 <= freq and freq <= 10):
|
|
num = 128
|
|
elif(10 < freq and freq <22):
|
|
num = 64
|
|
elif(22 <= freq and freq <= 42):
|
|
num = 32
|
|
else:
|
|
num = 32
|
|
if(freq > 42):
|
|
freq = 42
|
|
frame = int(1000000/(freq*(num+1)))
|
|
for i in range(0,num-1):
|
|
start = datetime.datetime.now()
|
|
if num == 256:
|
|
data = (FullSine8Bit[i] - 2047) * (amp/float(self.voltage)) *2
|
|
elif num == 128:
|
|
data = (FullSine7Bit[i] - 2047) * (amp/float(self.voltage)) *2
|
|
elif num == 64:
|
|
data = (FullSine6Bit[i] - 2047) * (amp/float(self.voltage)) *2
|
|
elif num == 32:
|
|
data = (FullSine5Bit[i] - 2047) * (amp/float(self.voltage)) *2
|
|
else:
|
|
data = (FullSine5Bit[i] - 2047) * (amp/float(self.voltage)) *2
|
|
data = int(data + offset*(4096/float(self.voltage)))
|
|
if data <= 0:
|
|
data = 0
|
|
if data >= 4095:
|
|
data = 4095
|
|
data = data <<4
|
|
self._send_data(data,channel)
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - start).microseconds
|
|
while looptime <= frame:
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - start).microseconds
|
|
|
|
def output_triangle(self,amp,freq,offset,dutyCycle,channel):
|
|
'''!
|
|
@brief Call the function to output triangle wave
|
|
@param amp Set triangle wave amplitude Vp
|
|
@param freq Set triangle wave frequency f
|
|
@param offset Set triangle wave DC offset Voffset
|
|
@param dutyCycle Set triangle (sawtooth) wave duty cycle
|
|
@param channel Output channel. 0: channel 0; 1: channel 1; 2: all the channels
|
|
'''
|
|
maxV = int(amp*(4096/float(self.voltage)))
|
|
if freq > 20:
|
|
num = 16
|
|
elif freq >= 11 and freq<=20:
|
|
num = 32
|
|
else:
|
|
num = 64
|
|
frame = 1000000/(freq*num*2)
|
|
if dutyCycle > 100:
|
|
dutyCycle = 100
|
|
if dutyCycle < 0:
|
|
dutyCycle = 0
|
|
up_num = (2*num)*(float(dutyCycle)/100)
|
|
down_num = ((2*num) - up_num)
|
|
if up_num == 0:
|
|
up_num = 1
|
|
for i in range(0,(maxV-int(maxV/up_num)-1),int(maxV/up_num)):
|
|
starttime = datetime.datetime.now()
|
|
enterV = i + int(offset*(4096/float(self.voltage)))
|
|
if enterV > 4095:
|
|
enterV = 4095
|
|
elif enterV < 0:
|
|
enterV = 0
|
|
enterV = enterV <<4
|
|
self._send_data(enterV,channel)
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
while looptime <= frame:
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
|
|
for i in range(0,int(down_num)):
|
|
starttime = datetime.datetime.now()
|
|
enterV = maxV-1-(i*int(maxV/down_num))+int(offset*(4096/float(self.voltage)))
|
|
if enterV > 4095:
|
|
enterV = 4095
|
|
elif enterV < 0:
|
|
enterV = 0
|
|
enterV = enterV <<4
|
|
self._send_data(enterV,channel)
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
while looptime <= frame:
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
|
|
def output_square(self,amp,freq,offset,dutyCycle,channel):
|
|
'''!
|
|
@brief Call the function to output square wave
|
|
@param amp Set square wave amplitude Vp
|
|
@param freq Set square wave frequency f
|
|
@param offset Set square wave DC offset Voffset
|
|
@param dutyCycle Set square wave duty cycle
|
|
@param channel Output channel. 0: channel 0; 1: channel 1; 2: all the channels
|
|
'''
|
|
maxV = int(amp*(4096/float(self.voltage)))
|
|
if freq > 20:
|
|
num = 16
|
|
elif freq >= 11 and freq<=20:
|
|
num = 32
|
|
else:
|
|
num = 64
|
|
frame = 1000000/(freq*num*2)
|
|
if dutyCycle > 100:
|
|
dutyCycle = 100
|
|
if dutyCycle < 0:
|
|
dutyCycle = 0
|
|
up_num = (2*num)*(float(dutyCycle)/100)
|
|
down_num = ((2*num) - up_num)
|
|
if up_num == 0:
|
|
up_num = 1
|
|
for i in range(int(up_num)):
|
|
starttime = datetime.datetime.now()
|
|
enterV = int(maxV + offset*(4096/float(self.voltage)))
|
|
if enterV > 4095:
|
|
enterV = 4095
|
|
elif enterV < 0:
|
|
enterV = 0
|
|
enterV = enterV <<4
|
|
self._send_data(enterV,channel)
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
while looptime <= frame:
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
for i in range(int(down_num)):
|
|
starttime = datetime.datetime.now()
|
|
enterV = int(maxV - offset*(4096/float(self.voltage)))
|
|
if enterV > 4095:
|
|
enterV = 4095
|
|
elif enterV < 0:
|
|
enterV = 0
|
|
self._send_data(enterV,channel)
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
while looptime <= frame:
|
|
endtime = datetime.datetime.now()
|
|
looptime = (endtime - starttime).microseconds
|
|
|
|
def _send_data(self,data,channel):
|
|
if channel == 0:
|
|
self.i2c.write_word_data(self._addr,self.GP8403_CONFIG_CURRENT_REG,data)
|
|
|
|
elif channel == 1:
|
|
self.i2c.write_word_data(self._addr,self.GP8403_CONFIG_CURRENT_REG<<1,data)
|
|
else:
|
|
self.i2c.write_word_data(self._addr,self.GP8403_CONFIG_CURRENT_REG,data)
|
|
self.i2c.write_word_data(self._addr,self.GP8403_CONFIG_CURRENT_REG<<1,data)
|
|
|
|
def _start_signal(self):
|
|
GPIO.output(self._scl, GPIO.HIGH)
|
|
GPIO.output(self._sda, GPIO.HIGH)
|
|
time.sleep(self.I2C_CYCLE_BEFORE)
|
|
GPIO.output(self._sda, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_AFTER)
|
|
GPIO.output(self._scl, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_TOTAL)
|
|
|
|
def _stop_signal(self):
|
|
GPIO.output(self._sda, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_BEFORE)
|
|
GPIO.output(self._scl, GPIO.HIGH)
|
|
time.sleep(self.I2C_CYCLE_TOTAL)
|
|
GPIO.output(self._sda, GPIO.HIGH)
|
|
time.sleep(self.I2C_CYCLE_TOTAL)
|
|
|
|
def _recv_ack(self, ack = 0):
|
|
ack_ = 0
|
|
error_time = 0
|
|
GPIO.setup(self._sda, GPIO.IN)
|
|
time.sleep(self.I2C_CYCLE_BEFORE)
|
|
GPIO.output(self._scl, GPIO.HIGH)
|
|
time.sleep(self.I2C_CYCLE_AFTER)
|
|
while GPIO.input(self._sda) != ack:
|
|
time.sleep(0.000001)
|
|
error_time += 1
|
|
if error_time > 250:
|
|
break
|
|
ack_ = GPIO.input(self._sda)
|
|
time.sleep(self.I2C_CYCLE_BEFORE)
|
|
GPIO.output(self._scl, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_AFTER)
|
|
GPIO.setup(self._sda, GPIO.OUT)
|
|
return ack_
|
|
|
|
def _send_byte(self, data, ack = 0, bits = 8, flag = True):
|
|
i = bits
|
|
data = data & 0xFF
|
|
while i > 0:
|
|
i -= 1
|
|
if data & (1 << i):
|
|
GPIO.output(self._sda, GPIO.HIGH)
|
|
else:
|
|
GPIO.output(self._sda, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_BEFORE)
|
|
GPIO.output(self._scl, GPIO.HIGH)
|
|
time.sleep(self.I2C_CYCLE_TOTAL)
|
|
GPIO.output(self._scl, GPIO.LOW)
|
|
time.sleep(self.I2C_CYCLE_AFTER)
|
|
if flag:
|
|
return self._recv_ack(ack)
|
|
else:
|
|
GPIO.output(self._sda, GPIO.LOW)
|
|
GPIO.output(self._scl, GPIO.HIGH)
|
|
return ack
|
|
|