SheffieldMLtracking / bee_track

Bumblebee Tracking System to run on Raspberry Pi
https://docs.google.com/document/d/1502XEZiBlq8zBkCZ7OQDWJYq8gfGQxDF87-0LBQ3b8Q/edit?usp=sharing
GNU General Public License v3.0
0 stars 0 forks source link

Flash Limit and 6 flash problem #17

Open Aplefen1 opened 1 month ago

Aplefen1 commented 1 month ago

Current problems we have found (don't worry Mike, relax on holiday, just assigning this so you see it when you come back)

  1. Flashes have an internal limit of 80 flashes at the power we are using a. After that they have to be physically turned off b. Current workaround is using physical switch and running around turning them off c. Ordered MOSFAT switches which can be controlled by Pi pins, 3.3v output? d. Change Trigger.py to turn off and on flashes after 60/70 flashes e. Flashes also have internal temperature limit...

  2. Can't seem to pulse flashes under 0.5 seconds?

  3. Flashing all 6 at the same time seems like a lot, change buck transformer, but doesn't seem like we will be getting too much more juice?

  4. Found that increasing output voltage on BT from 12.6v to around 13.5v seems to give a bit more leeway, especially with charging batteries (limit is 14.4v)

  5. Worringly on some of the pi hat boards, there seems to be a short on Flash 5/6, doesn't seem consistent? 2 boards with the potential problem

jlwoodgate commented 1 month ago

import time import datetime import RPi.GPIO as GPIO from configurable import Configurable import multiprocessing

class Trigger(Configurable): def init(self,message_queue,cam_trigger,t=2.0): super().init(message_queue) print("Initialising Trigger Control")
self.cam_trigger = cam_trigger self.debug = False self.manager = multiprocessing.Manager() self.flashselection = self.manager.list() self.flash_power_sel = self.manager.list()

    self.index = multiprocessing.Value('i',0)
    self.record = self.manager.list()
    self.direction = 0

    self.flash_select_pins = [14,15,18,23,5,22] #[8,10,12,16] #Board->BCM pins
    self.power_to_flash_pins = [27,17] #[top,bottom] only 2 available

    self.trigger_pin = 24 #18 #Board->BCM pins
    times_fired = []
    for i in range(len(self.flash_select_pins)):
        self.flashselection.append(i)
        times_fired.append(0)

    self.times_fired = self.manager.Array('i',times_fired)

    self.flash_power_sel.append(0) # top
    self.flash_power_sel.append(1) # bottom

    self.t = multiprocessing.Value('d',t)
    self.ds = multiprocessing.Value('d',0)
    self.flashseq = multiprocessing.Value('i',0) #0 = flash all, 1 = flash 2 at a time, 1 = flash in sequence,
    self.skipnoflashes = multiprocessing.Value('i',0) #how many to skip
    self.max_flashes = multiprocessing.Value('i',40)
    self.total_flashes = multiprocessing.Value('i',0)
    self.preptime = 0.02
    self.triggertime = 0.03 #this will end up at least 200us
    self.seqn = 0
    GPIO.setmode(GPIO.BCM) #GPIO.BOARD) #Board->BCM
    GPIO.setup(self.trigger_pin, GPIO.OUT)

    for pin in self.flash_select_pins:
        GPIO.setup(pin, GPIO.OUT)

    for pin in self.power_to_flash_pins:
        GPIO.setup(pin, GPIO.OUT)
    time.sleep(0.5)
    for pin in self.flash_select_pins:
        GPIO.output(pin, False)
    for pin in self.power_to_flash_pins:
        GPIO.output(pin, True)
    GPIO.output(self.trigger_pin, False)
    print("Running")
    self.run = multiprocessing.Event()

def trigger_camera(self,fireflash,endofset):
    """
        Send trigger to camera (and flash)
        fireflash = boolean: true=fire flash
        endofset = boolean: whether this is the last photo of a set (this will then tell the tracking system to look for the bee).
    """
    self.power_control()
    if self.debug:
        print("Photo:    Flash" if fireflash else "Photo: No Flash")

    if fireflash:
        if self.flashseq.value==0:
            for flash in self.flashselection:
                GPIO.output(self.flash_select_pins[flash],True)
                self.times_fired[flash] += 1
                self.total_flashes.value += 1
        if self.flashseq.value==1:
            GPIO.output(self.flash_select_pins[self.flashselection[self.seqn]],True)
            GPIO.output(self.flash_select_pins[self.flashselection[self.seqn+1]],True)
            self.times_fired[self.seqn] += 1
            self.times_fired[self.seqn+1] += 1
            self.total_flashes.value += 1
            self.seqn+=2
            if self.seqn>=len(self.flashselection):
                self.seqn = 0
        if self.flashseq.value==2:
            GPIO.output(self.flash_select_pins[self.flashselection[self.seqn]],True)
            self.times_fired[self.seqn] += 1
            self.total_flashes.value += 1
            self.seqn+=1
            if self.seqn>=len(self.flashselection):
                self.seqn = 0
        if self.flashseq.value==9:
            for pin in self.flash_select_pins:
                GPIO.output(pin, False)
    else:
        for pin in self.flash_select_pins:
            GPIO.output(pin, False)
    time.sleep(self.preptime)
    triggertime = time.time() #TODO Why are these two different?
    triggertimestring = datetime.datetime.now() #need to convert to string later

    triggertimestring = triggertimestring.strftime("%Y%m%d_%H:%M:%S.%f")
    self.record.append({'index':self.index.value,'endofset':endofset,'direction':self.direction,'flash':fireflash,
        'flashselection':list(self.flashselection),'triggertime':triggertime,'triggertimestring':triggertimestring})
    print("Incrementing trigger index from %d" % self.index.value) 
    self.index.value = self.index.value + 1

    #Software trigger...
    #self.cam_trigger.set()

    #Trigger via pin...
    GPIO.output(self.trigger_pin,True)

    time.sleep(self.triggertime)
    for pin in self.flash_select_pins:
        GPIO.output(pin, False)

    #(trigger via pin)...
    GPIO.output(self.trigger_pin,False)

def power_control(self):
    #Top 2 are controlled together, bottom 4 are controlled together
    #After flash 2 has fired 65 times, turn off top 2 for 2 flashes
    #After flast 6 has fired 70 times, turn off top 2 for 2 flashes

    if self.times_fired[1] == 25:
        self.total_flashes.value = 0
        GPIO.output(self.power_to_flash_pins[0], False)
        print("TURNED OFF TOP")

    elif self.times_fired[1] >= 25 and self.total_flashes.value >= 3:
        GPIO.output(self.power_to_flash_pins[0], True)
        print("TURNED ON TOP")

    if self.times_fired[5] == 30:
        self.total_flashes.value = 0
        GPIO.output(self.power_to_flash_pins[1], False)
        print("TURNED OFF BOTTOM")

    elif self.times_fired[5] >= 30 and self.total_flashes.value >= 3:
        GPIO.output(self.power_to_flash_pins[1], True)
        print("TURNED ON BOTTOM")

    print(self.times_fired)

    for count in range(len(self.times_fired)):
        if self.times_fired[count] > self.max_flashes.value:
            self.times_fired[count] = 0

def worker(self):
    skipcount = 0
    while (True):
        self.run.wait()
        delaystart = self.ds.value*self.t.value
        time.sleep(delaystart);
        skipcount+=1
        skipnoflashphoto = (skipcount<=self.skipnoflashes.value)
        self.trigger_camera(True,skipnoflashphoto)
        if not skipnoflashphoto:
            self.trigger_camera(False,True)
            skipcount = 0

            time.sleep(self.t.value-self.triggertime*2-self.preptime*2-delaystart)
        else:
            time.sleep(self.t.value-self.triggertime-self.preptime-delaystart)
jlwoodgate commented 1 month ago

import time
import datetime
import RPi.GPIO as GPIO
from configurable import Configurable
import multiprocessing

class Trigger(Configurable):
    def __init__(self,message_queue,cam_trigger,t=2.0):
        super().__init__(message_queue)
        print("Initialising Trigger Control")  
        self.cam_trigger = cam_trigger
        self.debug = False
        self.manager = multiprocessing.Manager()
        self.flashselection = self.manager.list()
        self.flash_power_sel = self.manager.list()

        self.index = multiprocessing.Value('i',0)
        self.record = self.manager.list()
        self.direction = 0

        self.flash_select_pins = [14,15,18,23,5,22] #[8,10,12,16] #Board->BCM pins
        self.power_to_flash_pins = [27,17] #[top,bottom] only 2 available

        self.trigger_pin = 24 #18 #Board->BCM pins
        times_fired = []
        for i in range(len(self.flash_select_pins)):
            self.flashselection.append(i)
            times_fired.append(0)

        self.times_fired = self.manager.Array('i',times_fired)

        self.flash_power_sel.append(0) # top
        self.flash_power_sel.append(1) # bottom

        self.t = multiprocessing.Value('d',t)
        self.ds = multiprocessing.Value('d',0)
        self.flashseq = multiprocessing.Value('i',0) #0 = flash all, 1 = flash 2 at a time, 1 = flash in sequence,
        self.skipnoflashes = multiprocessing.Value('i',0) #how many to skip
        self.max_flashes = multiprocessing.Value('i',40)
        self.total_flashes = multiprocessing.Value('i',0)
        self.preptime = 0.02
        self.triggertime = 0.03 #this will end up at least 200us
        self.seqn = 0
        GPIO.setmode(GPIO.BCM) #GPIO.BOARD) #Board->BCM
        GPIO.setup(self.trigger_pin, GPIO.OUT)

        for pin in self.flash_select_pins:
            GPIO.setup(pin, GPIO.OUT)

        for pin in self.power_to_flash_pins:
            GPIO.setup(pin, GPIO.OUT)
        time.sleep(0.5)
        for pin in self.flash_select_pins:
            GPIO.output(pin, False)
        for pin in self.power_to_flash_pins:
            GPIO.output(pin, True)
        GPIO.output(self.trigger_pin, False)
        print("Running")
        self.run = multiprocessing.Event()

    def trigger_camera(self,fireflash,endofset):
        """
            Send trigger to camera (and flash)
            fireflash = boolean: true=fire flash
            endofset = boolean: whether this is the last photo of a set (this will then tell the tracking system to look for the bee).
        """
        self.power_control()
        if self.debug:
            print("Photo:    Flash" if fireflash else "Photo: No Flash")

        if fireflash:
            if self.flashseq.value==0:
                for flash in self.flashselection:
                    GPIO.output(self.flash_select_pins[flash],True)
                    self.times_fired[flash] += 1
                    self.total_flashes.value += 1
            if self.flashseq.value==1:
                GPIO.output(self.flash_select_pins[self.flashselection[self.seqn]],True)
                GPIO.output(self.flash_select_pins[self.flashselection[self.seqn+1]],True)
                self.times_fired[self.seqn] += 1
                self.times_fired[self.seqn+1] += 1
                self.total_flashes.value += 1
                self.seqn+=2
                if self.seqn>=len(self.flashselection):
                    self.seqn = 0
            if self.flashseq.value==2:
                GPIO.output(self.flash_select_pins[self.flashselection[self.seqn]],True)
                self.times_fired[self.seqn] += 1
                self.total_flashes.value += 1
                self.seqn+=1
                if self.seqn>=len(self.flashselection):
                    self.seqn = 0
            if self.flashseq.value==9:
                for pin in self.flash_select_pins:
                    GPIO.output(pin, False)
        else:
            for pin in self.flash_select_pins:
                GPIO.output(pin, False)
        time.sleep(self.preptime)
        triggertime = time.time() #TODO Why are these two different?
        triggertimestring = datetime.datetime.now() #need to convert to string later

        triggertimestring = triggertimestring.strftime("%Y%m%d_%H:%M:%S.%f")
        self.record.append({'index':self.index.value,'endofset':endofset,'direction':self.direction,'flash':fireflash,
            'flashselection':list(self.flashselection),'triggertime':triggertime,'triggertimestring':triggertimestring})
        print("Incrementing trigger index from %d" % self.index.value) 
        self.index.value = self.index.value + 1

        #Software trigger...
        #self.cam_trigger.set()

        #Trigger via pin...
        GPIO.output(self.trigger_pin,True)

        time.sleep(self.triggertime)
        for pin in self.flash_select_pins:
            GPIO.output(pin, False)

        #(trigger via pin)...
        GPIO.output(self.trigger_pin,False)

    def power_control(self):
        #Top 2 are controlled together, bottom 4 are controlled together
        #After flash 2 has fired 65 times, turn off top 2 for 2 flashes
        #After flast 6 has fired 70 times, turn off top 2 for 2 flashes

        if self.times_fired[1] == 25:
            self.total_flashes.value = 0
            GPIO.output(self.power_to_flash_pins[0], False)
            print("TURNED OFF TOP")

        elif self.times_fired[1] >= 25 and self.total_flashes.value >= 3:
            GPIO.output(self.power_to_flash_pins[0], True)
            print("TURNED ON TOP")

        if self.times_fired[5] == 30:
            self.total_flashes.value = 0
            GPIO.output(self.power_to_flash_pins[1], False)
            print("TURNED OFF BOTTOM")

        elif self.times_fired[5] >= 30 and self.total_flashes.value >= 3:
            GPIO.output(self.power_to_flash_pins[1], True)
            print("TURNED ON BOTTOM")

        print(self.times_fired)

        for count in range(len(self.times_fired)):
            if self.times_fired[count] > self.max_flashes.value:
                self.times_fired[count] = 0

    def worker(self):
        skipcount = 0
        while (True):
            self.run.wait()
            delaystart = self.ds.value*self.t.value
            time.sleep(delaystart);
            skipcount+=1
            skipnoflashphoto = (skipcount<=self.skipnoflashes.value)
            self.trigger_camera(True,skipnoflashphoto)
            if not skipnoflashphoto:
                self.trigger_camera(False,True)
                skipcount = 0

                time.sleep(self.t.value-self.triggertime*2-self.preptime*2-delaystart)
            else:
                time.sleep(self.t.value-self.triggertime-self.preptime-delaystart)