# Filename to be printed
Thisfile = "LFMk2d.py"
# REQUIRES UKMARS.py 28/4/22
# History
#14/12/2021 starter
# 11/1/2022 OldError
# 13/1/2022 Switches on button-press, derivative inclusion
# 26/1/22    All changes made in this file
# 9 feb Fall-off detection changed
#    Fall-off error changed from 60 -
#    Fall-off speed new
# 7/4/22 speed = swval/2  dfactor 25 mult 0.3 looptime .005
# fast start at 100 for 0.3 seconds
# 5/9/2022  speed adjustment on curveature
#  increases slowly to maxspeed if in centre of line
# instantly slows to minspeed if not in centre (see line 122)
# tuned for 660RPM motors
# 18/5/22
# logfile function and stop marker detection added

#### imports
from machine import Pin, PWM, ADC,UART
import time, utime
from UKMARS import *   # SW1, Button, lfront , rfront, Motor

minspeed = 30  #(set  by switches line 109)
maxspeed = 90  #(NOT set  by switches line 110)
accell   = 2 # accelleration on the straight

speed = 0      # changed inside main loopo
mult = 0.3                 # used for tuning  (0.3 is reasonable)
dfactor = 20                # used for tuning (5 is reasonable) 

FOError = 70            # Fall-off error (was 60)
FOlevel = 30            # Fall-off sensor value (was 20)
                        # larger number makes it fall  off sooner
FOSpeed = 30            # Fall-off speed. (speed when fallen off)
# fall-off error and speed dictate curvature or steering back to line.

#############
#   Data    #
#############
# motors
LeftMotor  = Motor("L")    # set up left motor object
RightMotor = Motor("R")    # set up right motor object
lspeed=0                   # speed of left motor
rspeed=0                   # speed of right motor

error = 0                  # calculated from sensors
OldError = 0               # used to track previous error
change =0                  # calculated from sensors
StopAt = 3                 # marker count to stop at

############
#  logtxt  #
############
# record stuff to log file
def logtext():
    pfile = open("log.txt","a")
    pfile.write("\r\n\r\nspeed="+str(speed))
    pfile.write("\r\nmult="+str(mult))
    pfile.write("\r\ndfactor="+str(dfactor))
    pfile.write("\r\nloops="+str(loopcount)+" "+str(loopcount/160))
    pfile.close()
    print("log.txt written")
	
#################
#  setspeeds()  #
#################
'''
 Function to calculate error and motor speeds from the sensor values
 new for WKS9z
   detects fall-off at a tunable sensor level
   uses a tunable fall-off error value
   uses a tunable speed if fallen off
'''
def setspeeds(ls,rs): # ls and rs are the sensor readings 
    global lspeed,rspeed   # Python to let this function change speeds
    global error,OldError,mult      # to allow changing error

    myspeed = speed

    if (ls >FOlevel or rs >FOlevel):  # detect not fallen off
        led.off()
        error = ls-rs      # only if on-line,
    else:       
        led.on()           # Fall-off detected
        # Off-line, so boost error
        if error >0:
            error = FOError
        else:
            error = -FOError
        #myspeed = FOSpeed   # run at fall-off speed
        
    val = error *mult      # adjust steering amount

    # Derivative calculations, using last-time's value
    change = (error - OldError)
    # add in the derivative to val
    val = val + (change * dfactor)/10

    lspeed = myspeed - val   # speed of left motor
    rspeed = myspeed + val   # speed of right motor
    OldError = error       # keep track of this error for later
    return (error)

#############
# CountStop #
#############
markerCount = 0
overMarker = False

def CountStop():
    global overMarker,markerCount
    ssense = reads(stopsense.read_u16()) # read stop sensor    
    if (overMarker == True):  # if already over marker
        if (ssense <40):      # if no longer over marker
            overMarker = False
    else:
        if (ssense >60):      # if over marker
            markerCount = markerCount+1
            print (markerCount)
            overMarker = True
    return(markerCount)

	


##########
#  main  #
##########

RightMotor.stop()     #stop the motors just in case
LeftMotor.stop()

print(Thisfile)

# pre race set-up to print the workings, and check everything
while Button.value()==0:    # wait for Start button button to be pressed
    lsense = calibl(lfront.read_u16()) # read left front sensor
    rsense = calibr(rfront.read_u16()) # read right front sensor
    ssense = calibs(stopsense.read_u16()) # read stop sensor    
    
    setspeeds(lsense,rsense)  # set up error from readings
    CountStop()                 # check stop marker
    
    print ("L ",lsense," R ",rsense,"Error",error,markerCount)  # print the sensor values and error
    time.sleep(0.1)     # wait 100 milliseconds

swval = readswitches()   # read value of 4-way switch
if swval != 150 :  # ignore if ON,ON,ON,ON
    minspeed = swval
#    maxspeed = minspeed + 30

print("Speeds="+str(minspeed)+"  "+str(maxspeed))
	
# main loop to actually run the track
loopcount = 0
speed = minspeed
written=0  # whether logfile has been written
markerCount = 0
overMarker = False
while True:
    lsense = calibl(lfront.read_u16()) # read left front sensor
    rsense = calibr(rfront.read_u16()) # read right front sensor
    setspeeds(lsense,rsense)  # set up speeds from readings

    CountStop()                 # check stop marker
    if (speed != 0):
        if (error >35 or error <-35):
            if (maxspeed - speed < 20):
                LeftMotor.speed(-20)  # set left motor speed
                RightMotor.speed(-20) # set right motor speed
                #time.sleep(0.01)        # wait 5 milliseconds

            speed = minspeed
        else:
            speed = min(speed+accell,maxspeed)

    LeftMotor.speed(lspeed)  # set left motor speed
    RightMotor.speed(rspeed) # set right motor speed

    time.sleep(0.005)        # wait 6 milliseconds
    loopcount = loopcount + 1

    # stop on stop marker if StopAt markers reached
    if (markerCount >= StopAt):
        speed = 0             # stop motors
        if(written == 0):
            logtext()
            written=1
        
    

# end of loop
# never gets here   