FFC control with Python and purethermal2

2,472 views
Skip to first unread message

jens...@gmail.com

unread,
Nov 21, 2018, 4:10:19 AM11/21/18
to Flir Lepton

Hi! 

I was wondering if anyone has any experience with FFC control with Python and PureThermal 2?
I am using it for temperature measurements and need to control when the FFC is preformed. 

My camera is the Lepton 3.5.

Any help is greatly appreciated!

Cheers,
Jens

Karl Parks

unread,
Nov 21, 2018, 4:36:50 PM11/21/18
to Flir Lepton
Hello Jens,

I don't necessarily have answer for you but I once spoke the GroupGets purethermal1-firmware developer Kurt Kiefer who gave me this email response asking about setting Low or High Gain, which I believe would be set similarly to FFC. (I compiled it from two emails):

"There’s a python file inside the same directory of your script [https://github.com/groupgets/purethermal1-uvc-capture/tree/master/python] that we created (you’re importing it) that manually defines a bunch of the CCI functions, so you can call them from python code. You have to add the definitions to it for any CCI functions you need to call. GetThermal is a little different, since it actually uses the FLIR SDK directly. Looking at GetThermal will just tell you what functions you need to define.

[Second Email]

You're going to use the "call_extension_unit" function. You need to figure out which extension unit to use (corresponding to the FLIR module AGC, RAD, VID, SYS, etc., these are already defined in uvctypes... hint it's SYS for this one based on the function name), and what the control id to call (from 1-N for any given unit). See here for an explanation of how to calculate the control id from the lepton register offset, you'll look in the FLIR SDK header file to find the register offset: https://github.com/groupgets/purethermal1-firmware/wiki/Lepton-CCI-through-UVC-extension-units"

Unfortunately, I was never able to figure it out and had to move onto other tasks at work. Please let me know if you have any results. Mr. Kiefer was working out of pocket so he wasn't able to help much more past that. 

Karl

jens...@gmail.com

unread,
Nov 28, 2018, 10:50:27 AM11/28/18
to Flir Lepton
Hi thanks for the reply,

So, what I have done up until now is to download the uvc-capture repository from your link and tried to make sense of what is said in the IDD manual for the Lepton cameras (https://www.flir.com/globalassets/imported-assets/document/flir-lepton-software-interface-description-document.pdf). What I have achieved is something that does not work, but does not feel tooooo far off either. This is the python code that I have simply added to the uvctypes.py:

def set_manual_ffc(devh):
   shutter_mode
= create_string_buffer(16)
   set_extension_unit
(devh, SYS_UNIT_ID, 80, shutter_mode, 16) #set_extension_unit(devh, unit, control, data, size)

where 80 comes from this calculation (it's corect right?), as the Set value in the IDD is 0x3D:
control_id=(0x3D >> 2) + 1 =80

But, when I try to load this to the lepton 3.5 nothing changes, it continues to close the shutter every 3 minutes, even though I am trying to set it to manual.

Any idea what I am doing wrong? I load it to the camera by running set_manual_ffc(devh) in the uvc-deviceinfo.py script

Cheers,
Jens

Kurt Kiefer

unread,
Nov 28, 2018, 12:41:56 PM11/28/18
to Flir Lepton
The shutter_mode variable shouldn't be 16 bytes wide, it should be 2. You will also need to initialize it to the value you need. And mind the endianness.

Kurt Kiefer

unread,
Nov 28, 2018, 12:43:34 PM11/28/18
to Flir Lepton
Also, your calculation for control_id doesn't look right.


On Wednesday, November 28, 2018 at 7:50:27 AM UTC-8, jens...@gmail.com wrote:

jens...@gmail.com

unread,
Nov 29, 2018, 4:27:21 AM11/29/18
to Flir Lepton
Hi, Kurt! 

I am not sure if I follow. From the IDD document, the length of the data is stated to be 16. Should I still put it to be 2 (see attached photo)? And what should I initialize it to if I f.ex. want to make it operate in manual mode (to 0?)? I thought that all the command info was given in the control-id (control_id = (command id (0x3D for SET) + mode (0 for manual) >> 2 )+1?)

For the calculation, I did this:
contol_id =(0x3D >> 2)+1
         
=61>>2+1
         
=(00111101>>2)+1
         
=(01001111)+1
         
=(79)+1 =80

I guess some of my assumptions here are wrong? Super grateful for the help :)


Screenshot 2018-11-29 at 08.52.53.png

Cheers,
Jens 

jens...@gmail.com

unread,
Nov 29, 2018, 4:49:33 AM11/29/18
to Flir Lepton
Just to be sure;
If I set the FFC made to be manual, it will only preform an FFC when I call on the SYS Run FFC Normalization command? By using those two commands, can I have complete control over the FFC timing?

cheers,
Jens

Kurt Kiefer

unread,
Nov 29, 2018, 3:04:20 PM11/29/18
to Flir Lepton
Well, it sounds like the SDD is talking about size in bits, not bytes. The API you're actually calling expects size to be determined in bytes.

You can take a look at the Lepton SDK (which the PT1/2 firmware ends up calling internally when you're accessing the extension units API) to see the different enumeration values you can set for a particular function, if this isn't listed in the SDD.

Kurt

David

unread,
Dec 10, 2018, 6:05:47 AM12/10/18
to flir-...@googlegroups.com
So we have another option for files and discussions, there is now a
(FLIR) Lepton group on Facebook.  All are welcome.

David


Andrew V. Jones

unread,
Dec 10, 2018, 6:10:11 AM12/10/18
to David, flir-...@googlegroups.com
Can you link to this? I searched for it, but couldn’t find it.
> --
> You received this message because you are subscribed to the Google
> Groups "Flir Lepton" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to flir-lepton...@googlegroups.com.
> Visit this group at https://groups.google.com/group/flir-lepton.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/flir-lepton/28e3ab65-c797-1297-22d5-07d1b36e30d9%40hiwaay.net.
> For more options, visit https://groups.google.com/d/optout.

David

unread,
Dec 10, 2018, 7:51:13 AM12/10/18
to Andrew V. Jones, flir-...@googlegroups.com
https://www.facebook.com/groups/2115968165090395/

Bear in mind, it's BRAND new, without content yet.  I was way too sleepy
to start populating it yet.  :(

David

Al Bencomo

unread,
Dec 10, 2018, 3:18:55 PM12/10/18
to Flir Lepton
I'm afraid that Facebook will not be a good alternative since members will not be necessarily in the right mindset.  They're more likely to be logged in to Facebook to be social so you will be competing with other Facebook ‘noise’. It's also difficult to keep track of topics in Facebook (i.e. easy for things to be missed) and it has a poor search functionality.

I suggest using Slack instead since it is integrated with services we use everyday like GitHub and provide better real-time collaboration and search.

Anyhow, I don't have any ties to Slack; this is just a personal opinion/suggestion.

Andrew Jones

unread,
Dec 10, 2018, 3:22:10 PM12/10/18
to Al Bencomo, Flir Lepton
I think anywhere we can share cool stuff to do with the Lepton is awesome :)

Google Groups is great because it is easily searchable.

--
You received this message because you are subscribed to the Google Groups "Flir Lepton" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flir-lepton...@googlegroups.com.
Visit this group at https://groups.google.com/group/flir-lepton.

Karl Parks

unread,
Dec 10, 2018, 6:23:20 PM12/10/18
to Andrew Jones, Al Bencomo, Flir Lepton
Has anyone use the flir lepton community forum? That's a pretty nice workspace. One benefit of facebook is that you can share your projects with your friends and family a little bit easier.

Karl


For more options, visit https://groups.google.com/d/optout.
--
Aerospace Engineering Major
Computer Science Minor
San Diego State University
(530) 526-7030 | kheirl...@gmail.com

David

unread,
Dec 10, 2018, 10:07:15 PM12/10/18
to flir-...@googlegroups.com

True, Andrew.  My idea is to augment, not replace.

David

unread,
Dec 10, 2018, 10:08:03 PM12/10/18
to flir-...@googlegroups.com

My thoughts exactly.  And it's a backup.  :)

David

unread,
Dec 10, 2018, 10:25:40 PM12/10/18
to flir-...@googlegroups.com
With Google+ going away, will that affect our Google group?

Karl Parks

unread,
May 30, 2019, 1:16:13 PM5/30/19
to Flir Lepton
Hello Jens,

Were you ever successful in your endeavor to control FFC with Python? I'm trying to figure out how to control Gain Mode.

Karl

Karl Parks

unread,
May 30, 2019, 4:32:37 PM5/30/19
to Flir Lepton
Kurt,

I thought I had everything figured out but I still can't get the FFC command to work from uvctypes.py. I am having trouble with the difference between the get and set control_id. The bitwise operation suggested in Lepton-CCI-through-UVC-extension-units unfortunately removes the difference in the SDK get/set commands, which I believe is the source of my issue.

From page 68 of the IDD,
SDK Command ID: 
- Base 0x3C With 
- Get   0x3C With 
- Set    0x3D

Both of the below operations yield an identical control id which I believe is the source of my issue.
(0x3C >> 2) + 1 = 16
(0x3D >> 2) + 1 = 16

Any help? I know I am doing this mostly correct because for the flir serial number, I followed the same process using 0x08 from the SDK which yields (0x08 >> 2) + 1 = 3 as used in print_device_info of uvctypes. 

Best,

Karl

Kurt Kiefer

unread,
May 30, 2019, 5:26:23 PM5/30/19
to Flir Lepton
You've got it right, 0x3C (LEP_CID_SYS_FFC_SHUTTER_MODE_OBJ) should be register 16. The same control ID is used for both GET_CUR and SET_CUR. You can also see that it's the same as used here https://github.com/groupgets/purethermal1-uvc-capture/blob/master/v4l2/uvcdynctrl/pt1.xml

Based on the information you've given me, it sounds ok. So what else can you look at? Are you performing a uvc_set_ctrl (set_extension_unit in the python wrapper)? Do you have the size set to 2 bytes? Are you selecting the SYS unit?

Karl Parks

unread,
May 30, 2019, 6:49:54 PM5/30/19
to Flir Lepton
def set_manual_ffc(devh):
    sizeData
= 32
    shutter_mode
= create_string_buffer(sizeData)
   
#0x200 Module ID VID
   
#0x3C get
   
#0x3D set
    getSDK
= 0x3D
    controlID
= (getSDK >> 2) + 1 #formula from Kurt Kiefer
   
print('controlID: ' + str(controlID))
    set_extension_unit
(devh, SYS_UNIT_ID, controlID, shutter_mode, sizeData) #set_extension_unit(devh, unit, control, data, size)
   
print("Shutter Mode #: {0}".format(repr(shutter_mode.raw)))

The above variables: 
SYS_UNIT_ID = 6
controlID = 16
shutter_mod = create_string_buffer(32)
sizeData = 32

This is what my function looks like in uvctypes... I tried for sizeData 2, 4, 8, 16, and 32.

I call the function in uvc-deviceinfo.py... and it should perform a FFC, correct? Right now it doesn't do anything.

Karl

Kurt Kiefer

unread,
May 30, 2019, 6:51:33 PM5/30/19
to Flir Lepton
The enumeration value should be an integer of size 2 bytes, not a string.

Karl Parks

unread,
May 30, 2019, 6:56:44 PM5/30/19
to Flir Lepton
I tried run FFC as well. 

def perform_manual_ffc(devh):
    sizeData
= 2 #should be size 32 bytes?

    shutter_mode
= create_string_buffer(sizeData)
   
#0x200 Module ID VID
   
#0x3C get
   
#0x3D set
    getSDK
= 0x3D

    runFFC
= 0x42
    controlID
= (runFFC >> 2) + 1 #formula from Kurt Kiefer

   
print('controlID: ' + str(controlID))
    set_extension_unit
(devh, SYS_UNIT_ID, controlID, shutter_mode, sizeData) #set_extension_unit(devh, unit, control, data, size)
   
print("Shutter Mode #: {0}".format(repr(shutter_mode.raw)))

Kurt Kiefer

unread,
May 30, 2019, 6:58:21 PM5/30/19
to Flir Lepton
I don't know where your 0x42 came from? Look at the SDK:

typedef enum LEP_SYS_FFC_SHUTTER_MODE_E_TAG
{
   LEP_SYS_FFC_SHUTTER_MODE_MANUAL = 0,
   LEP_SYS_FFC_SHUTTER_MODE_AUTO,
   LEP_SYS_FFC_SHUTTER_MODE_EXTERNAL,

   LEP_SYS_FFC_SHUTTER_MODE_END

}LEP_SYS_FFC_SHUTTER_MODE_E, *LEP_SYS_FFC_SHUTTER_MODE_E_PTR;

Kurt Kiefer

unread,
May 30, 2019, 7:00:46 PM5/30/19
to Flir Lepton
Or maybe I don't understand what you're trying to do. If you want to run a command, the "Lepton CCI through UVC extension units" document says you should perform a set with the size 1 byte.

Karl Parks

unread,
May 30, 2019, 7:17:23 PM5/30/19
to Flir Lepton
IT WORKED! I was able to perform a FFC Normalization. Just 1 byte... should of seen that. "Lepton CCI Run commands are implemented as 1-byte controls."

Thank you so much Kurt! 

I'm still having trouble switching between modes but I think I can figure out the rest from here.

Karl Parks

unread,
May 30, 2019, 8:12:42 PM5/30/19
to Flir Lepton
What enumeration value should I pass to turn my shutter_mode back to Auto? 

Karl

Karl Parks

unread,
Jun 5, 2019, 8:45:50 PM6/5/19
to Flir Lepton
Kurt,

I can now perform FFC on command and switch between Gain States no problem by passing the reference of c_uint16 variable.

However I am struggling with switching between FFC modes, more along the lines of the original question from Jens. I can switch to Manual FFC mode no problem but when I switch back to Auto, the lepton shutter starts performing a FFC every 3 seconds instead of the 3 minutes. I was wondering how I would go about passing more information (such as the frequency of the shutter) to the lepton?

Current code below:

def set_auto_ffc(devh):
    sizeData
= 4
    shutter_mode
= (c_uint16)(1)

   
#0x200 Module ID VID
   
#0x3C get
   
#0x3D set
    getSDK
= 0x3D
    controlID
= (getSDK >> 2) + 1 #formula from Kurt Kiefer
   
print('controlID: ' + str(controlID))

    set_extension_unit
(devh, SYS_UNIT_ID, controlID, byref(shutter_mode), sizeData) #set_extension_unit(devh, unit, control, data, size)

According to the IDD, it looks like I'll need to pass two variables. One for the struct, and one for the enum. Page 69.
Message has been deleted

Karl Parks

unread,
Jun 23, 2019, 9:39:59 PM6/23/19
to Flir Lepton
Hey everyone (reposting this),

Just an update that I have a pretty strong code here in the latest updates to Parabilis Thermalhttps://github.com/Kheirlb/purethermal1-uvc-capture You can now change FFC and Gain Modes! If you flip through the settings too fast things do get crazy so be aware.

A little strange, but these are the default settings for the lepton shutter which doesn't seem to correlate super well with the IDD but it works. 

# Default Shutter Info: (1, 0, 0, 0, 1, 0, 1, 0, 48928)
#  1  shutterMode
#  0  tempLockoutState
#  0  videoFreezeDuringFFC
#  0  ffcDesired
#  1  elapsedTimeSinceLastFfc
#  0  desiredFfcPeriod
#  True  explicitCmdToOpen
#  0  desiredFfcTempDelta
#  48928 imminentDelay

If anyone can explain to me why desiredFfcPeriod doesn't return 180000 someday that would be great!

Thanks Kurt for all of the help!

Cheers,

Kurt Kiefer

unread,
Jun 24, 2019, 1:14:02 AM6/24/19
to Flir Lepton
Karl,

That looks like a very fine effort, thanks for sharing!


#  48928 imminentDelay

If anyone can explain to me why desiredFfcPeriod doesn't return 180000 someday that would be great!

Without having looked into ANY of the details about the calls you're referring to, your problem sticks out like a sore thumb to a salty C programmer:

180000 decimal -> 0x2BF20 hex
truncate the result to 16 bits / 2-bytes (unsigned short): 0x2BF20 & 0xFFFF -> 0xBF20 hex -> 48928 decimal

I guess that whatever function you're calling wants to return a 32-bit / 4-byte word (unsigned long), but you're only asking for 16 bits.

Kurt

蔡黎强

unread,
Nov 25, 2019, 9:21:33 AM11/25/19
to Flir Lepton
hello, Karl:

It's really amazing and easy using for your update uvctypes library. 
But during using, I found another problem that the function 'set_gain_auto(devh)' would not be worked correct that the max temp is stopped at 180degreeC same as low gain mode. 
I guess whether we need to reset the FFC mode into auto by the function 'set_auto_ffc(devh)' ?
def set_gain_auto(devh):
sizeData = 4
gain_mode = (c_uint16)(2) #0=HIGH, 1=LOW, 2=AUTO
setGainSDK = 0x49
controlID = (setGainSDK >> 2) + 1 #formula from Kurt Kiefer
print('controlID: ' + str(controlID))
set_extension_unit(devh, SYS_UNIT_ID, controlID, byref(gain_mode), sizeData) #set_extension_unit(devh, unit, control, data, size)
perform_manual_ffc(devh)
 


def set_auto_ffc(devh):
sizeData = 32
shutter_mode = (c_uint16)(1)
getSDK = 0x3D
controlID = (getSDK >> 2) + 1 #formula from Kurt Kiefer
print('controlID: ' + str(controlID))
set_extension_unit(devh, SYS_UNIT_ID, controlID, byref(sysShutterAuto), sizeData)

cai

在 2019年6月24日星期一 UTC+8上午9:39:59,Karl Parks写道:
Hey everyone (reposting this),

Just an update that I have a pretty strong code here in the latest updates to Parabilis Thermalhttps://github.com/Kheirlb/purethermal1-uvc-capture You can now change FFC and Gain Modes! If you flip through the settings too fast things do get crazy so be aware.

A little strange, but these are the default settings for the lepton shutter which doesn't seem to correlate super well with the IDD but it works. 

# Default Shutter Info: (1, 0, 0, 0, 1, 0, 1, 0, 48928)
#  1  shutterMode
#  0  tempLockoutState
#  0  videoFreezeDuringFFC
#  0  ffcDesired
#  1  elapsedTimeSinceLastFfc
#  0  desiredFfcPeriod
#  True  explicitCmdToOpen
#  0  desiredFfcTempDelta
#  48928 imminentDelay

If anyone can explain to me why desiredFfcPeriod doesn't return 180000 someday that would be great!

Thanks Kurt for all of the help!
<div style="background-color: transparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-family: &q

在 2019年6月24日星期一 UTC+8上午9:39:59,Karl Parks写道:
Hey everyone (reposting this),

Just an update that I have a pretty strong code here in the latest updates to Parabilis Thermalhttps://github.com/Kheirlb/purethermal1-uvc-capture You can now change FFC and Gain Modes! If you flip through the settings too fast things do get crazy so be aware.

A little strange, but these are the default settings for the lepton shutter which doesn't seem to correlate super well with the IDD but it works. 

# Default Shutter Info: (1, 0, 0, 0, 1, 0, 1, 0, 48928)
#  1  shutterMode
#  0  tempLockoutState
#  0  videoFreezeDuringFFC
#  0  ffcDesired
#  1  elapsedTimeSinceLastFfc
#  0  desiredFfcPeriod
#  True  explicitCmdToOpen
#  0  desiredFfcTempDelta
#  48928 imminentDelay

If anyone can explain to me why desiredFfcPeriod doesn't return 180000 someday that would be great!

Thanks Kurt for all of the help!
<div style="background-color: transparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-family: &q

Nadav Silverman

unread,
Jun 21, 2020, 1:54:16 AM6/21/20
to Flir Lepton
Hi Cai,

I was wondering if you can hep me with a method I'm having a hard time implementing.
Apparently I don't understand the syntax of the SDK. I am coding in python and I can't seem to get some 'set' commands to work.
In the "Quick Start Guide: Getting Started Programing with the Python SDK" I saw the command "lep.vid.SetPcolorLut(0)". according to that template I tried changing the FFC mode to manual with lep.sys.SetFfcShutterModeObj(0) but I get the following error:

Traceback (most recent call last):
  File "cci_and_image.py", line 27, in <module>
    lep.sys.SetFfcShutterModeObj(0)
TypeError: No method matches given arguments for SetFfcShutterModeObj


I get the same error when trying other 'set' commands like SetFramesToAverage.
What is the correct syntax for those methods and what arguments do they receive? 
I tried to implement your way of calling the methods but I Don't understand where do all this arguments you use in the method come from. They don't appear in the documentation.

Tanks,
Nadav


בתאריך יום שני, 25 בנובמבר 2019 בשעה 16:21:33 UTC+2, מאת 蔡黎强:
Reply all
Reply to author
Forward
0 new messages