diff --git a/installation_file.txt b/installation_file.txt new file mode 100644 index 0000000000000000000000000000000000000000..a6f708959132d71cc3fb516cc8b5d876ec71abbe --- /dev/null +++ b/installation_file.txt @@ -0,0 +1,10 @@ +sudo apt-get install python3-venv (déjà installé) +sudo apt-get install libatlas-base-dev +mkdir python-virtual-environments +cd python-virtual-environments +python3 -m venv ohmpi +source ohmpi/bin/activate +pip install RPi.GPIO +pip install adafruit-blinka +pip install numpy +pip install adafruit-circuitpython-ads1x15 diff --git a/ohmpy_v_1_01.py b/ohmpy_v_1_01.py index dab5eab78e3b6fe1b122b5eb9b95882583fcb48a..95a51fa4815aca2cb522440a1fd93eddc20be1e7 100644 --- a/ohmpy_v_1_01.py +++ b/ohmpy_v_1_01.py @@ -6,17 +6,42 @@ OHMPY, it has been developed by Rémi CLEMENT,Vivien DUBOIS, Nicolas FORQUET (IR print 'OHMPI start' print MyDateTime.isoformat() print 'Import library' +print('OHMPI start' ) +print('Import library') #!/usr/bin/python import RPi.GPIO as GPIO import time import datetime +from datetime import datetime import board import busio import numpy import os +import sys import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn +import pandas as pd +import os.path + +""" +display start time +""" +current_time = datetime.now() +print(current_time.strftime("%Y-%m-%d %H:%M:%S")) + +""" +parameters +""" +nb_electrodes = 32 # maximum number of electrodes on the resistivity meter +injection_duration = 0.5 # Current injection duration in second +nbr_meas= 1 # Number of times the quadripole sequence is repeated +sequence_delay= 30 # Delay in seconds between 2 sequences +stack= 1 # repetition of the current injection for each quadripole +R_ref = 50 # reference resistance value in ohm +coef_p0 = 2.02 # slope for current conversion for ADS.P0, measurement in ??? +coef_p1 = 2.02 # slope for current conversion for ADS.P1, measurement in ??? +export_path = "/home/pi/Desktop/ohmpy-develop/measurement.csv" """ functions @@ -29,7 +54,106 @@ def switch_mux(quadripole): for j in range(0,5) : GPIO.output(int(quadmux[i,j]), bool(path2elec[quadripole[i]-1,j])) +# function to find rows with identical values in different columns +def find_identical_in_line(array_object): + output = [] + if array_object.ndim == 1: + temp = numpy.zeros(4) + for i in range(len(array_object)): + temp[i] = numpy.count_nonzero(array_object == array_object[i]) + if any(temp > 1): + output.append(0) + else: + for i in range(len(array_object[:,1])): + temp = numpy.zeros(len(array_object[1,:])) + for j in range(len(array_object[1,:])): + temp[j] = numpy.count_nonzero(array_object[i,:] == array_object[i,j]) + if any(temp > 1): + output.append(i) + return output + +# read quadripole file and apply tests +def read_quad(filename, nb_elec): + output = numpy.loadtxt(filename, delimiter=" ",dtype=int) # load quadripole file + # locate lines where the electrode index exceeds the maximum number of electrodes + test_index_elec = numpy.array(numpy.where(output > 32)) + # locate lines where an electrode is referred twice + test_same_elec = find_identical_in_line(output) + # if statement with exit cases (rajouter un else if pour le deuxième cas du ticket #2) + if test_index_elec.size != 0: + for i in range(len(test_index_elec[0,:])): + print("Error: An electrode index at line "+ str(test_index_elec[0,i]+1)+" exceeds the maximum number of electrodes") + sys.exit(1) + elif len(test_same_elec) != 0: + for i in range(len(test_same_elec)): + print("Error: An electrode index is used twice at line " + str(test_same_elec[i]+1)) + sys.exit(1) + else: + return output + +# perform a measurement +def run_measurement(nb_stack, injection_deltat, Rref, coefp0, coefp1): + i2c = busio.I2C(board.SCL, board.SDA) # I2C protocol setup + ads = ADS.ADS1115(i2c, gain=2/3) # I2C communication setup + # inner variable initialization + sum_I=0 + sum_Vmn=0 + sum_Ps=0 + # GPIO initialization + GPIO.setmode(GPIO.BCM) + GPIO.setwarnings(False) + GPIO.setup(7, GPIO.OUT) + GPIO.setup(8, GPIO.OUT) + # resistance measurement + for n in range(0,3+2*nb_stack-1) : + if (n % 2) == 0: + GPIO.output(7, GPIO.HIGH) # polarité n°1 + else: + GPIO.output(7, GPIO.LOW) # polarité n°1 également ? + GPIO.output(8, GPIO.HIGH) # current injection + time.sleep(injection_deltat) # delay depending on current injection duration + Ia1 = AnalogIn(ads,ADS.P0).voltage * coefp0 # reading current value on ADS channel A0 + Ib1 = AnalogIn(ads,ADS.P1).voltage * coefp1 # reading current value on ADS channel A1 + Vm1 = AnalogIn(ads,ADS.P2).voltage # reading voltage value on ADS channel A2 + Vn1 = AnalogIn(ads,ADS.P3).voltage # reading voltage value on ADS channel A3 + GPIO.output(8, GPIO.LOW)# stop current injection + I1= (Ia1 - Ib1)/Rref + sum_I=sum_I+I1 + Vmn1= (Vm1 - Vn1) + if (n % 2) == 0: + sum_Vmn=sum_Vmn-Vmn1 + sum_Ps=sum_Ps+Vmn1 + else: + sum_Vmn=sum_Vmn+Vmn1 + sum_Ps=sum_Ps+Vmn1 + # return averaged values + output = pd.DataFrame({ + "time":[datetime.now()], + # rajouter les ABMN + "Vmn":[sum_Vmn/(3+2*nb_stack-1)], + "I":[sum_I/(3+2*nb_stack-1)], + "R":[sum_Vmn/(3+2*nb_stack-1)/(sum_I/(3+2*nb_stack-1))], + "Ps":[sum_Ps/(3+2*nb_stack-1)], + "nbStack":[nb_stack] + }) + print(output.to_string()) + return output + +# save data +def append_and_save(path, last_measurement): + + if os.path.isfile(path): + # Load data file and append data to it + with open(path, 'a') as f: + last_measurement.to_csv(f, header=False) + else: + # create data file and add headers + with open(path, 'a') as f: + last_measurement.to_csv(f, header=True) +""" +Initialization of GPIO channels +""" GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) @@ -53,32 +177,26 @@ sequence_delay= 30 # Delay in Second between 2 sequences stack= 1 # repetition of the current injection for each quadrupole """ -Reading the quadripole file +Main loop """ -N=numpy.loadtxt("ABMN.txt", delimiter=" ",dtype=int) # load quadripole file +N=read_quad("ABMN.txt",nb_electrodes) # load quadripole file for g in range(0,nbr_meas): # for time-lapse monitoring - """ - Selection electrode activées pour chaque quadripole - """ - for i in range(0,N.shape[0]): # boucle sur les quadripôles, qui tient compte du nombre de quadripole dans le fichier ABMN - # call switch_mux function + for i in range(0,N.shape[0]): # loop over quadripoles + # call the switch_mux function to switch to the right electrodes switch_mux(N[i,]) - time.sleep(injection_time); + # run a measurement + current_measurement = run_measurement(stack, injection_duration, R_ref, coef_p0, coef_p1) + + # save data and print in a text file + append_and_save(export_path, current_measurement) + + # reset multiplexer channels GPIO.output(12, GPIO.HIGH); GPIO.output(16, GPIO.HIGH); GPIO.output(20, GPIO.HIGH); GPIO.output(21, GPIO.HIGH); GPIO.output(26, GPIO.HIGH) GPIO.output(18, GPIO.HIGH); GPIO.output(23, GPIO.HIGH); GPIO.output(24, GPIO.HIGH); GPIO.output(25, GPIO.HIGH); GPIO.output(19, GPIO.HIGH) GPIO.output(6, GPIO.HIGH); GPIO.output(13, GPIO.HIGH); GPIO.output(4, GPIO.HIGH); GPIO.output(17, GPIO.HIGH); GPIO.output(27, GPIO.HIGH) GPIO.output(22, GPIO.HIGH); GPIO.output(10, GPIO.HIGH); GPIO.output(9, GPIO.HIGH); GPIO.output(11, GPIO.HIGH); GPIO.output(5, GPIO.HIGH) - - time.sleep(sequence_delay);#waiting next measurement - - - - -''' -Save result in txt file -''' - + time.sleep(sequence_delay) #waiting next measurement (time-lapse) \ No newline at end of file