
'''
A script for the AS7262 color sensor using Adafruit Blinka and the Pimoroni Inky pHAT

Based on the AS726X/Circuit Python and Inky pHAT example codes by Adafruit ans Pimoroni

Version: Dec 31 2018 HF
Requires Adafuit Blinka, Circuit Python AS726X, and the Inky pHaT libraries, and GPIOzero.

'''
# libraries

# General
import time
import datetime

# Blinka
import board
import digitalio
import busio

# AS7262
from adafruit_as726x import Adafruit_AS726x

#GPIOzero
from gpiozero import Button, LED
from signal import pause

# for Inky pHAT
import sys
from PIL import ImageFont
import inkyphat

# CSV function
import csv

# definitions

b_button = Button (24)       # Momentary button at GPIO 24
m_button = Button (23)       # Momentary button at GPIO 23
led = LED(16)                #LED at GPIO 16. Do not use GPIO 4 or 17.

inkyphat.set_colour('black')  # for b/w inky phat
#inkyphat.set_colour('red')  # for red inky phat
inkyphat.set_rotation(180)  # turn display 180°

font1 = ImageFont.truetype(inkyphat.fonts.FredokaOne, 16) # Select standard font header
font2 = ImageFont.truetype(inkyphat.fonts.FredokaOne, 14) # Select standard font data

# define language "EN", "DE", ...
lang = "EN"

#Initialize

# Try digital") input
pin= digitalio.DigitalInOut(board.D4)
print ("Digital IO OK")

#Try I2C
i2c = busio.I2C(board.SCL, board. SDA)
print ("I2C ok")
sensor = Adafruit_AS726x(i2c)
print ()

#AS7262 settings
sensor.conversion_mode = sensor.MODE_2 # mode_2: contious reading of all 6 channels
sensor.gain = 1                        # 1, 3.7, 16, 64; default 64 adjust if required
sensor.integration_time = 360          # between 2.8 and 714 ms; default: 140 

''' 
# blank values (manual setting, required in basic version)
v0 = 18650
b0 = 20490
g0 = 28980
y0 = 47420
o0 = 35000
r0 = 28760
'''

CSV_name = 'Meas_AS7262-2.csv'

#functions
def get_timestamp():   #get timestamp

        ts0_EN ='{:%Y-%m-%d}'.format(datetime.datetime.now()) # timestamp - date EN
        ts0_DE ='{:%d.%m.%Y}'.format(datetime.datetime.now()) # timestamp - date DE/german
        ts1='{:%H:%M:%S}'.format(datetime.datetime.now()) # timestamp - time

        if (lang =="DE"):
            ts0 = ts0_DE

        else:
            ts0 = ts0_EN

        ts = ts0 + " " + ts1
        return ts

def init_csv(CSV_Name):
    with open (CSV_Name,'w', newline='') as csvfile:
        fieldnames = ['timestamp', 'v','b','g','y','o','r', 'type']
        csv_writer = csv.DictWriter(csvfile,fieldnames=fieldnames)
        csv_writer.writeheader()
        #csv_writer.close()

def write_to_csv(CSV_Name, t_stamp, values, typ):   #timestamp, vales (as tuple) and type (B or M)
    with open (CSV_Name,'a', newline='') as csvfile:
        fieldnames = ['timestamp', 'v','b','g','y','o','r', 'type']
        csv_writer = csv.DictWriter(csvfile,fieldnames=fieldnames)
        # extract value tupels
        v_c = ("{0:0.1f}".format(values[0]) )
        b_c = ("{0:0.1f}".format(values[1]) )
        g_c = ("{0:0.1f}".format(values[2]) )
        y_c = ("{0:0.1f}".format(values[3]) )
        o_c = ("{0:0.1f}".format(values[4]) )
        r_c = ("{0:0.1f}".format(values[5]) )
        
        csv_writer.writerow({'timestamp': t_stamp,'v':v_c, 'b':b_c, 'g':g_c, 'y':y_c, 'o':o_c, 'r':r_c,'type':typ})


def blank(): # read blank values

    while not sensor.data_ready:
        time.sleep(.1)

    #read calibrated values from sensor
    violet = sensor.violet
    blue = sensor.blue
    green = sensor.green 
    yellow = sensor.yellow
    orange = sensor.orange
    red = sensor.red
    b_val =(violet, blue, green, yellow, orange, red)  # blanks as tuple
        
    led.on()       #reading sensor indicator
    time.sleep (1)
    led.off()

    # get timestamp
    ts = get_timestamp()

    # print timestamp to display 
    print (ts)
    print ()

    # write to csv
    write_to_csv(CSV_name, ts, b_val, 'B')    
    return b_val
    

def measure():           #perform measurement
    while not sensor.data_ready:
        time.sleep(.1)
        
    #read calibrated values from sensor
    violet = sensor.violet
    blue = sensor.blue
    green = sensor.green 
    yellow = sensor.yellow
    orange = sensor.orange
    red = sensor.red
 
    led.on()      # sensor read indicator
    time.sleep (1)
    led.off()
    # pause()

    # reads channel-compensated values, not the raw values
    print ("calibrated values")         
    print ("V: " + str(int(violet)))
    print ("B: " + str(int(blue)))
    print ("G: " + str(int(green)))
    print ("Y: " + str(int(yellow)))
    print ("O: " + str(int(orange)))
    print ("R: " + str(int(red)))
    print (" \n")

    # calculate transluminescence in %
    t_v = 100*violet/v0
    t_b = 100*blue/b0
    t_g = 100*green/g0
    t_y = 100*yellow/y0
    t_o = 100*orange/o0
    t_r = 100*red/r0
    t_val = (t_v, t_b, t_g, t_y, t_o, t_r)                        

    # print transluminescence values to screen 
    print ("T_v: " + str(round(t_v)) + " %")
    print ("T_b: " + str(round(t_b)) + " %")
    print ("T_g: " + str(round(t_g)) + " %")
    print ("T_y: " + str(round(t_y)) + " %")
    print ("T_o: " + str(round(t_o)) + " %")
    print ("T_r: " + str(round(t_r)) + " %")
    print (" \n")

    # bargraph transluminescence values, 50x "=" equals 100%
    print ("T_V: " + int(t_v/2)*'=')
    print ("T_B: " + int(t_b/2)*'=')
    print ("T_G: " + int(t_g/2)*'=')
    print ("T_Y: " + int(t_y/2)*'=')
    print ("T_O: " + int(t_o/2)*'=')
    print ("T_R: " + int(t_r/2)*'=')
    print ("    |" + 10*'____|')
    print ("\n")

    # get timestamp
    ts = get_timestamp()

    # print timestamp to display 
    print (ts)
    print ()

    # write to csv
    write_to_csv(CSV_name, ts, t_val, 'M')                         

    # print values to Inky pHAT
    # set tabs (simplifies optimization of layout)
    t1 = 5   # tab 1, frist column 
    t2 = 30  # tab 2, second column
    t3 = 100  # tab 3, 3rd column
    t4 = 160 # tab 4, not used here
    
    # write timestamp
    inkyphat.clear()
    inkyphat.text((t1, 0), ts, inkyphat.BLACK, font2) # write timestamp
    #inkyphat.text((t3, 0), ts1, inkyphat.BLACK, font2) # write timestamp time
    inkyphat.line((t1, 16, 207,16), 1,3)               # draw a horizontal line
    inkyphat.line((t3-15,16, t3-15,111), 1,3)          # draw a vertical line

    # write transluminescence values
    inkyphat.text((t1, 18), "V: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 18), ("{0:0.1f}".format(t_v) + "%"), inkyphat.BLACK, font2)
    inkyphat.text((t1, 32), "B: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 32), ("{0:0.1f}".format(t_b) + "%"), inkyphat.BLACK, font2)
    inkyphat.text((t1, 46), "G: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 46), ("{0:0.1f}".format(t_g) + "%"), inkyphat.BLACK, font2)
    inkyphat.text((t1, 60), "Y: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 60), ("{0:0.1f}".format(t_y) + "%"), inkyphat.BLACK, font2)
    inkyphat.text((t1, 74), "O: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 74), ("{0:0.1f}".format(t_o) + "%"), inkyphat.BLACK, font2)
    inkyphat.text((t1, 88), "R: ", inkyphat.BLACK, font2)
    inkyphat.text((t2, 88), ("{0:0.1f}".format(t_r) + "%"), inkyphat.BLACK, font2)

    # draw bargraph    
    inkyphat.rectangle((t3, 21,(t3 + 100), 21+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK) 
    inkyphat.rectangle((t3, 35,(t3 + 100), 35+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 49,(t3 + 100), 49+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 63,(t3 + 100), 63+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 77,(t3 + 100), 77+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 91,(t3 + 100), 91+9),fill=inkyphat.WHITE, outline=inkyphat.BLACK)

    inkyphat.rectangle((t3, 21,(t3 + int(t_v)), 21+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK) 
    inkyphat.rectangle((t3, 35,(t3 + int(t_b)), 35+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 49,(t3 + int(t_g)), 49+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 63,(t3 + int(t_y)), 63+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 77,(t3 + int(t_o)), 77+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK)
    inkyphat.rectangle((t3, 91,(t3 + int(t_r)), 91+9),fill=inkyphat.BLACK, outline=inkyphat.BLACK)

    # write to Inky pHAT
    inkyphat.show()

#main part:

ts_csv = get_timestamp()
CSV_name = ("AS7262-"+ ts_csv +".csv")
init_csv(CSV_name)
                            
# Ouput to display
print ("Hello, this is a script for the AS7262 color sensor")
print ("using Adafruit Blinka and the Pimoroni Inky pHAT")
print ()
print ("Press button 'B' to perform a blank measurement")
print ("Press button 'M' to perform a measurement")
print ()
print ("Please start with a blank measurement ")
print ()
print ("Please now place the reference (blank) cuvette into photometer,")
print ("then press (white) B-button")
# b_button.wait_for_press()

# output on Inky pHAT
inkyphat.clear()
inkyphat.text((5, 5), "AS7262/Inky pHAT", inkyphat.BLACK, font1)
inkyphat.text((5, 20), "6 channel photometer", inkyphat.BLACK, font1)
inkyphat.text((5, 40), "First perform a blanks", inkyphat.BLACK, font1)
inkyphat.text((5, 55), "measurement. Insert", inkyphat.BLACK, font1)
inkyphat.text((5, 70), "reference cuvette ", inkyphat.BLACK, font1)
inkyphat.text((5, 85), "and press button B", inkyphat.BLACK, font1)
inkyphat.show()

b_button.wait_for_press()
        
#read blank values at start
b_val = blank()
v0 = int(b_val [0])
b0 = int(b_val [1])
g0 = int(b_val [2])
y0 = int(b_val [3])
o0 = int(b_val [4])
r0 = int(b_val [5])
                            
# write_to_csv('Start', b_val, 'B')        

#output to display
print ("Blanks measured")
print
print ("You may now perform your measurements")
print ()
print (" Press button 'M' for measurement")
print (" or button 'B' to reset blanks,")
print (" or both to stop the script")
print ()
print (" You may have to press buttons for up to two seconds!")

#output instructions to Inky pHAT
inkyphat.clear()
inkyphat.text((5, 5), "Starting blanks taken.", inkyphat.BLACK, font1)
inkyphat.text((5, 25), "For sample measurements", inkyphat.BLACK, font1)
inkyphat.text((5, 45), "press button M, to reset", inkyphat.BLACK, font1)
inkyphat.text((5, 65), "blanks press button B or", inkyphat.BLACK, font1)
inkyphat.text((5, 85), "both buttons to end.", inkyphat.BLACK, font1)

inkyphat.show()

# measurement loop
while True:
    
    if (m_button.is_pressed and b_button.is_pressed): # exit loop and end script
        led.on()
        time.sleep (.5)
        led.off()
        break
    
    elif m_button.is_pressed:        # evoke measurement sample
        measure ()
        print ("Measurement performed")
        print ("Press M or B or both")
        print ()
        
    elif b_button.is_pressed:        # measure and reset blank values
        blank ()
        #read blank values to reset
        b_val = blank()
        v0 = int(b_val [0])
        b0 = int(b_val [1])
        g0 = int(b_val [2])
        y0 = int(b_val [3])
        o0 = int(b_val [4])
        r0 = int(b_val [5])
        
        ts=get_timestamp()
        
        print ("Blanks have been redefined at " + ts)
        print ("Press buttons M or B or both")
        
        inkyphat.clear()
        inkyphat.text((5, 5), "Blanks redefined at", inkyphat.BLACK, font1)
        inkyphat.text((5, 25), ts, inkyphat.BLACK, font1)
        inkyphat.text((5, 70), "To measure samples,", inkyphat.BLACK, font1)
        inkyphat.text((5, 85), "press button M. ", inkyphat.BLACK, font1)
        inkyphat.show()

        
    else:
        time.sleep(2)
    
inkyphat.clear() # empty Inky pHAT display procedure,
inkyphat.show()  # silence for crontab-version  

print ("bye!")
