HAB Assistance Required

Etishere

New Member
Hello everyone

I am a new PICAXE and forum user.

We are a small team of guys taking part in BACAR 5
"Balloon carrying Amateur Radio" we are putting together a "Cube Sat" box that will be part of 12 other payloads to launch on 21 October in Secunda South Africa.
We are running out of time to get the coding right.
we are running a picaxe 401 mainboard with its shield, we connected two temperature sensors and a LDR to measure light intencity.
the main BACAR program runs fine and we can see the sensor readings in the terminal window.

we have connected a camera / video camera to record stills and video of our near space flight, this code included below for reference:

Camera:

high B.5 'Camera On
pause 250
low B.5
pause 250
wait 5

Video:

toggle B.7 ; toggle output 7
pause 10000 ; wait for 10 seconds
wait 15

goto Camera: ; loop back to start

This code works fine by itself, but as soon as I insert it into the main program / code, something breaks and the camera / video don't work.
when I run the simulator, it seems to skip the code for the camera, I've tried entering the code here and there, but whereever I put it, it doesn't want to activate the pins / outputs.

I've read that I should be writing a SUB Routine instead, but am getting stumped on how to do this.

Basically the camera / video should be able to take pictures and video in sequence, at the same time as the picaxe is logging sensor readings.

Can anyone please help with the correct coding for this ?

Many thanks
Stephen
ZS6SKY
 

westaust55

Moderator
Welcome to the PICAXE forum.

To use subroutines the structure of the program would be along the following lines:
Code:
Main:
Do
; do something
  Gosub camera
; do something
  Gosub video
Loop ; loop back to the  Do forever

;subroutines
Camera:
; do camera stuff
  Return ; return back to main loop

Video:
; do video stuff
  Return ; return back to main loop
 

AllyCat

Senior Member
Hi Stephen,

Basically the camera / video should be able to take pictures and video in sequence, at the same time as the picaxe is logging sensor readings.
Welcome to the forum. I think the above may be the root of your problem, because a simple computer program can only perform a sequence of operations, one at a time. The PAUSE 10000 prevents anything else happening in those 10 seconds (and similarly the WAIT 5 and WAIT 15).

The PICaxe M2 chips offer two simple solutions, "Multitasking" (using several separate "Start:" points) and the "time" variable, which automatically "ticks" once each second (so you can write something like IF time = 10 THEN ...... .) But unfortunately neither method is directly applicable to the 28X2 chip that I believe you are using, so you will need to work around the problem in another way.

The "traditional" solution is to use "interrupts" (which can be considered as a rather special form of subroutine) but they can be complicated and may introduce more problems than they cure. However, you should be able to use a program arranged as a "polling" loop. In principle you would have a "main:" loop which starts with (for example) a PAUSE 1000 (or a WAIT 1), then performs some "instant" operations and then jumps back to the main: (start).

Instead of writing a WAIT 5 : do something , you could structure the program as follows:

Code:
SYMBOL  camerawait = b2
SYMBOL  videowait = b3
main:
   PAUSE 1000       ; A one second "tick"
   camerawait = camerawait + 1
   IF camerawait = 5 THEN
       GOSUB docamerastuff
       camerawait = 0
   ENDIF
   videowait = videowait + 1
   IF videowait = 15 THEN
       GOSUB dovideostuff
       videowait = 0
   ENDIF
   GOTO main

docamerastuff:      ; Subroutine that uses NO (long) PAUSEs or WAITs

   RETURN
dovideostuff:
;etc....
You might be able to use the PAUSE 250 in the subroutine, or may need to handle those in a similar way to the 1 second polling loop.

Cheers, Alan.
 

lbenson

Senior Member
Welcome.

We need to see more of your code in order to determine why in the simulator, "it seems to skip the code for the camera". (And we need "the big picture".)

Best to post the whole thing, but I understand that this may be a large program. If it is "modular" (as tends to be best with larger programs), it may be adequate to just post the "main loop" with an indication of what major subroutines do, something like:
Code:
...
main:
  do
    gosub something1 ' do this
    gosub something2 ' do that
    gosub camera       ' take a snap and record video
  loop
But in the code you posted, there is never a return (or goto) exiting the camera routine. Perhaps there is a similar problem with other tasks, which prevent them from being terminated.

I agree with other posters that for this type of program, you probably want to avoid "PAUSE" and "WAIT", and figure out a timer mechanism (perhaps using 250ms ticks), and do things when the various counters of ticks expire.

(Sounds like a great project--I assume you're familiar with "PICAXE is in Space": http://www.picaxeforum.co.uk/showthread.php?24846-PICAXE-is-in-Space .)
 
Last edited:

lbenson

Senior Member
For instance, this code will take a snapshot every half second, and a 10-second video every minute. (Runs in PE6 simulator, but not thoroughly tested.)
Code:
' 40BACAR5 picaxe 40X2 cube sat controller
#picaxe 40x2
#terminal 4800
#no_data
#no_table

symbol cVideoMinutes = 1 ' video every n minutes
symbol cVideoLapsedTics = cVideoMinutes * 240 ' # ticks between videos

'symbol b0 reserved for bit flags
symbol bSnap = bit0
symbol bVideo = bit1

symbol videoTicks = b4
symbol wStartVideo = w26
symbol wTickCount = w27

wTickCount = 0

main:
  do
    pause 250
    inc wTickCount
    if wTickCount > 57600 then gosub fixTicks ' 4 hours have elapsed
    gosub something1
    gosub something2
    gosub something3
    gosub Camera
    wStartVideo = wTickCount // cVideoLapsedTics ' e.g., every 5 minutes (4 ticks * 60 seconds * 5 minutes)
    if bvideo = 1 or wStartVideo = 0 or wStartVideo = 1 then gosub Video ' (don't mis-align ticks)
  loop

Camera: ' this will result in a snapshot every half second if video is not recording
  if bVideo = 0 then ' OK to snap or terminate snap
    if bSnap = 0 then ' start snap
      high B.5 'Camera On
      bSnap = 1
    else
      low B.5 'Camera Off
      bSnap = 0
    endif
  endif
  return
  

Video: ' this will result in a 10 second video if snapshot not in progress
  if bSnap = 0 then ' ok to start or stop video
    if bVideo = 0 then ' start video
      high B.7 'Video On
      bVideo = 1
      videoTicks = 0
    else
      inc videoTicks
      if videoTicks >= 40 then
        low B.7 'Video Off
        bVideo = 0
      endif
    endif
  endif
  return

something1:
  return

something2:
  return

something3:
  return

fixTicks: ' you may have to adjust other counters
  wTickCount = 0
  return
If you run this in the simulator, put breaks on lines 49 and 55 ("high B.7" and "low B.7"). Then run and tick the "Simulation Delay" time down to 0, and then click the "Memory" tab, you will see w27 counting up (eventually to 240), bit0 (shown as b0) and B.5 toggling on and off, indicating snapshot, and w26 counting up to 240 (indicating 4*60 or 1 minutes worth of 250ms ticks). At that point, you will break on "high B.7", and if you single step twice with Ctri+Space, B.7 will go high, indicating "video on". If you continue running and click "Memory", you will see b4 count up to 40, indicating 10 seconds worth of video. "low B.7" will be executed with the next single step.
40BACAR5 PE6.jpg
So the camera takes a snap every half second and video for 10 seconds every minute. These times can be changed. Meanwhile, every 250ms, something1, something2, and something3 are executed. As long as these routines have no significant PAUSE or WAIT statements, and similarly use tick counts to do necessary timings, all will perform in a sort-of multi-processing way--everything gets a time slice every 250 ms. Since the 40x2 can process about 2000 to 4000 statements a second, if there are no PAUSEs, the amount of time your code takes is probably negligible.

If critical, you could reduce the main loop PAUSE to 100.

Note that if you are reading DS18B20 temperature sensors with READTEMP, each READTEMP will take up to 750ms, and this will throw your timing off by a considerable amount. You can fix this by using the one-wire (OWIN, OWOUT) method of reading the DS18B20s (so if you initiate a DS18B20 sensor reading, after 3 ticks (750ms) you can read the result).
 
Last edited:

hippy

Technical Support
Staff member
Another welcome to the PICAXE forum.

There are probably quite a few elegant solutions to what you want to achieve but the best way to do it may depend on exactly what you want to do, what else needs to happen as well as triggering the camera and video.

If you have a list of all tasks - for example camera takes a shot every 5 seconds, video records for 20 seconds, stops for 20 seconds, then records again - that will probably help.
 

Etishere

New Member
PICAXE Feedback:

hi Alan and westaust55

Many thanks for the quick replies, I am at work now and managed a sneak peak of the forum, will see if i can play with the code tonight, otherwise its going to be tomorrow night.
So the way my program must run is that as the balloon goes up, the temperature sensors must continue to take samples at 1 sec intervals, inside and outside cube temperature.
the LDR continues to take light intensity samples at 1 sec intervals and the battery voltage is monitored at 1 sec intervals.
while this is happening, i want the camera to be taking pictures, let's say 5 then pause for 10 seonds, then take a video clip for 10 to 15 seconds, then loop back to taking pictures.
I still need to work out how many pictures I can take over the predicted 4 - 6 hour flight, I was working on 30 pictures in 10 minutes and a video clip a minute.

Any comments on whether this would work / can work like this ? and yes, I am using the 28X2 chip.

regards
Stephen
 

Etishere

New Member
hi All
Ok, I am now on the open internet where I can post replies for a while, thanks for the feedback thus far, I will only get a chance to play with the code posted tonight, and not being a fundy at this, its been very challenging thus far.

Hippy requested the full task list, so here is the full "Main" program below, then under that is the "Camera" program, that I need to run at the same time, I need to know where to insert the camera code ?
or if anyone can assist me with other code that will enable the pic to do the same job.
Basically the balloon will be launched at 9 am SA time on 21 October, our "Payload" is part of 12 payloads, some school payloads and a main payload with a test SA Amateur radio satellite "Kletskous" more info on www.sarl.org.za

Back to our payload, as it goes up - flight will be around 4 hours, it must take pictures and video clips and record info from the sensors installed on it.
Code:
'--------------------------- Set Picaxe type ---------------------
    #picaxe 28X2
'------------------------ Setup Symbols --------------------------
symbol Log_Counter =w0
symbol Counted_Logs =w1
symbol Flight_Trigger=pinC.2
symbol Memory_Add_I =w6
symbol Memory_Add_O =w7
symbol Char1=b16
symbol Log_Time =w10
symbol Log_T =w11
'------------------------ Setup Counters -------------------------
Log_Counter=30    'The number of logs to make during flight (NB max of 8000 redings for 512KBit's Memoru chip 24LC512) 
Log_Time=0    '# The time between logs In seconds up op 65535 (NB 0=1Sec ans 1=2Sec)
    
'----------------------- Setup EEPROM -----------------------------
    hi2csetup i2cmaster, %10100000, i2cfast, i2cword
'Is the Flight Pin Pulled Yes/No
    if Flight_Trigger=1 then
        'Yes (continue)
    else        
        'No 
'-----Set i2cEEPROM Add to 0----
        Memory_Add_I=0
        write 0,b12
        write 1,b13
        
        Counted_Logs=0
        write 2,b2
        write 3,b3
        
    sertxd (cr,lf," @@@@@@@@@@@@ Memory Reset @@@@@@@@@@ ",cr,lf)
        Log_T =0
        '-------------------------------
        goto main    
    end if
'------------------ Record Count full Yes/No -----------------------
    'read counted logs
    read 2,b2
    read 3,b3
    '------------------
    if Counted_Logs=Log_Counter then
        'Yes
        goto Read_Memory
    else        
        'No
        
        goto main    
    end if
'---------------------------  MAIN ----------------------------------

main: 
    
    pause 10'450
    low B.1
    
    '-------------------
    GoSub Battry_Voltage
    GoSub Read_LDR
    GoSub Read_temp1
    GoSub Read_temp2
    'Is the Flight Pin Pulled Yes/No
        if Flight_Trigger=1 then
        'Yes
            if log_Time <log_T then
                GoSub Data_To_Memmory
                Log_T=0
            endif 
        else        
        'No
            GoSub PC_Disply        
        end if
    '-------------------
    high B.1
    pause 10'450
    Log_T=Log_T+1
    sertxd (#log_T," ")
    'debug
goto main
'---------------------------Batary Voltage monitor--------------------
Battry_Voltage:
readadc A.0, W4
      w4 = w4 * 40/100          'Scale/MAP 40/100
       bintoascii W4,b6,b6,b6,b6,b7    
return
'----------------------------LDR Light intensity----------------------
Read_LDR:
    readadc A.1,W5 ; read ADC1 into variable b0
     'bintoascii W5,b18,b18,b18,b18,b19
return
'----------------------------Internal Tempratur-----------------------
Read_temp1:
    readtemp C.0,b24 ; read input 1 into variable b0
    'readtemp C.0,b25 ; read input 1 into variable b0
return
'----------------------------Externap Tempratur-----------------------
Read_temp2:
    readtemp C.1,b26 ; read input 1 into variable b0
    
return
'----------------------------Disply on PC Whill Flight pin In---------
PC_Disply:
    sertxd ("  ",b6,",",b7,"V")
    sertxd ("   LDR ",#w5," ")
    if b24 > 127 then
        let b25 = b24 - 128
        sertxd ("  I-Temp -",#b25," ")
    else
        sertxd ("  I-Temp ",#b24," ")
    end if
    '------------------------
    if b26 > 127 then
        let b27 = b26 - 128
        sertxd ("  E-Temp -",#b27,cr,lf)
    else
        sertxd ("  E-Temp ",#b26,cr,lf)
    end if
    
return




'=============================  Data to Memory =============================
Data_To_Memmory:
    read 0,b12
    read 1,b13
    'sertxd ("Mem Add ",#W6,cr,lf)
        
    if Log_Counter = Counted_Logs Then
        Goto Task_Comp
    else
        ' Increment log counter---------------------------------------------
        Counted_Logs=Counted_Logs+1
        sertxd (cr,lf,"Writing record ",#Counted_Logs,"  ")
        '-------------------------------------------------------------------
        'Write Start Byt to i2cEEPROM -------------------------------------------
        
        
        writei2c Memory_Add_I,("#") ' Start marker 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
        
        'Write Battart voltage to i2cEEPROM -------------------------------
        
        writei2c Memory_Add_I,(b6) ' write the Volt record to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
                
        writei2c Memory_Add_I,(b7) ' write the Milie Volt record to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
        
        'Write LDR to i2cEEPROM -------------------------------------------
        
        writei2c Memory_Add_I,(b10) ' write LDR record to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
                
        writei2c Memory_Add_I,(b11) ' write the LDR record to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
        
        'Write Internal Tempratur to i2cEEPROM----------------------------------
            
        writei2c Memory_Add_I,(b24) ' Internal Tempratur to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
                                
        'Write Ecternal Tempratur to i2cEEPROM----------------------------------
        
        writei2c Memory_Add_I,(b26) ' Ecternal Tempratur to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
                
                
        'Write Stop Byt to i2cEEPROM -------------------------------------------
        
        writei2c Memory_Add_I,("; ") ' write LDR record to memory 
        pause 10 ' wait 10 ms for write
        Memory_Add_I=Memory_Add_I+1
        
        'Store Memory Counter
        write 0,b12
        write 1,b13
        'Store counted logs
        write 2,b2
        write 3,b3
    end if
return
'---------------------------------------------------------------------
Read_Memory:
sertxd (cr,lf,"##################### READING MEMORY ##################",cr,lf)
        'Read last Addres
        read 0,b12
        read 1,b13
        sertxd ("End Addres= ",#Memory_Add_I,cr,lf)    
    For Memory_Add_O=0 to Memory_Add_I
    high B.1
    'Start byt
        pause 10 ' wait 10 ms for write
        readi2c Memory_Add_O,(Char1)
        pause 10 ' wait 10 ms for write
        sertxd (Char1," ")
        pause 10
        Memory_Add_O=Memory_Add_O+1
    'Voltage
        readi2c Memory_Add_O,(Char1)
        pause 10 ' wait 10 ms for write
        sertxd (Char1,",")
        pause 10
        Memory_Add_O=Memory_Add_O+1
    'Millie Voltage
        readi2c Memory_Add_O,(Char1)
        pause 10 ' wait 10 ms for write
        sertxd (Char1,"V ")
        pause 10
        Memory_Add_O=Memory_Add_O+1
    'LDR 
        readi2c Memory_Add_O,(b4)
        pause 10 ' wait 10 ms for write
        Memory_Add_O=Memory_Add_O+1
        readi2c Memory_Add_O,(b5)
        pause 10 ' wait 10 ms for write
        Memory_Add_O=Memory_Add_O+1
        sertxd ("Light_Intencity=",#W2,",")
        pause 10
        
    'Internal Tempratur
        readi2c Memory_Add_O,(b4)
        pause 10 ' wait 10 ms for write
        Memory_Add_O=Memory_Add_O+1
        
        if b4 > 127 then
            let b25 = b4 - 128
        sertxd ("  Inside_Cube-Temperature -",#b25," ")
        else
        sertxd ("  Inside_Cube-Temperature ",#b4," ")
        end if
        '---------LED Off-----------
        low B.1    
    'External Tempratur
        readi2c Memory_Add_O,(b4)
        pause 10 ' wait 10 ms for write
        Memory_Add_O=Memory_Add_O+1
        
        if b4 > 127 then
            let b27 = b4 - 128
        sertxd ("  Outside-Temperature -",#b27," ")
        else
        sertxd ("  Outside-Temperature ",#b4," ")
        end if
        
    'Stop Byt
        readi2c Memory_Add_O,(Char1)
        pause 10 ' wait 10 ms for write
        sertxd (Char1,cr,lf)
        pause 10
        
        
        
    Next Memory_Add_O
'return
'---------------------------------------------------------------------
Task_Comp:
    'pause 1000
    high B.1
    pause 200
    low B.1
    pause 200

Goto Task_Comp
'---------------------------------------------------------------------

Then the Camera Code below:

Camera:

high B.5    'Camera On
pause 250
low B.5
pause 250
wait 5

Video:

    toggle B.7     ; toggle output 7
    pause 10000 ; wait for 10 seconds
    wait 15
    
goto Camera:     ; loop back to start
Anyone's assistance will be greatly appreciated.

Regards
Stephen
 
Last edited by a moderator:

lbenson

Senior Member
Just a quick note--if you post code within the tags "[ code]" and "[ /code]" (without the spaces), what you have posted will be placed in a scrollable box and, more importantly, indentations (spaces and tabs) will be preserved--this will make your code easier to read, especially for anyone who copies it into the Program Editor and tries to work with it.
 

Etishere

New Member
Hi IBenson
Thanks, I've been reading your code now and I've got my cube here, will program it quickly, and see if the camera works, I just changed the 40 = 10 seconds to 80, so hopefully the camera will record 20 second video clips. i still need to know how i can insert your version, if it works, into the main code, so that everything runs together.
My BACAR.jpg
 

AllyCat

Senior Member
Hi Stephen,

Any comments on whether this would work / can work like this ?
Yes this is certainly possible with a PICaxe, but your program/requirements are (already) quite complex and you have only two weeks, of which the second should really be reserved for system testing. So here are a few "bullet points" on how I would attack the project:

Firstly, to help us all, as suggested above, put the program code above into about four sets of [ code] [ /code] tags, separately for "setup", "main", "measurements" and "logging" (data storage). There is rather a mixture of SYMBOL names and explicit basic Bytes and Words (W2, etc.). Ideally, symbolise ALL "global" variable names, but I usually reserve a few variables (B1, W1, etc.) for "Local" or "immediate" use, e.g. READTEMP pin,W1 : WRITE temperaturepointer,W1 , then W1 is available to be used for something else.

Secondly, create a table for the various measurements, listing how often (in seconds) each is to be repeated and how long the measurement (or event) will take to execute. You won't know all those values yet, but they can be guessed and refined as we proceed. For example it's clear that "Video" needs to be divided into "Start Video (recording)" and "Stop Video" events. Also, as mentioned by somebody above, READTEMP (using the 18B20 sensor) takes many hundreds of milliseconds to execute, so it may need some care with how it is used.

The code example I gave in #3 started "main:" with a PAUSE 1000 to keep the explanation simple, but you will need something more sophisticated. A good starting point might be to still use a main: polling loop cycle of one second, but use a structure like this:

Code:
symbol loop_left = w10    ; Remaining loop time in ms

main:
   loop_left = 990     ; milliseconds
   loop_number = loop_number + 1
   B1 = loop_number // 10    ; The "Remainder", i.e.  B1 continuously "counts" from 0 to 9
   IF B1 = 3 THEN GOSUB readtemp1    ; Or you might use a SELECT .. CASE statement
;   etc.
   PAUSE loop_left     ; Pad the loop time out to 1 second
   GOTO main

readtemp1:
   READTEMP pin,W1
   WRITE memory,W1
   loop_left = loop_left - 750   ; This subroutine took 750 ms (estimate)
RETURN
Finally, you have a number of SERTXDs (for debugging). They could remain in the final version (but never DEBUGs), but you would need to pay careful attention to how long the serial communications take to execute. The advantage is that you should never make large changes to your program near the end of the project! Alternatively, put the "debugging" code in compiler directives (#...) like this:

Code:
#DEFINE testing    ; Comment this line out for the final program

#IFDEF testing
   SERTXD(" Test Value is: ",#W10)
#ENDIF
Cheers, Alan.
 

lbenson

Senior Member
One question--it is unclear to me whether your snapshot shooter and your video camera are one and the same device or two separate instruments. Can you take snapshots while the video is recording, or is it either/or?
 

lbenson

Senior Member
If you are looking to read temperatures (and do other things) every second, you need to avoid READTEMP or READTEMP12, because they wait for the DS18B20 to measure and convert the temperature, which may take 750ms per read. You can work around these delays by using the one-wire commands, OWOUT and OWIN, to initiate a conversion and then do the read when the necessary time has elapsed (while doing other things).

This program shows how to read 4 DS18B20 sensors in 750ms with a 20X2 using OWOUT and OWIN (instead of the 3 seconds it would otherwise take to read the 4 sensors).
Code:
' 20owtemp reads ds18b20 with owout, owin
#picaxe 20x2
#no_table
#no_data

'settimer t1s_4       ' set timer to overflow in 1 second at 4mhz
'settimer t1s_1       ' set timer to overflow in 1 second at 4mhz
low  C.5 ' ground for ds18b20
high C.0 ' power for ds18b20
tmr3setup %10100001

main:
  do
    timer3 = 0
    owout C.1,%1001,($CC,$44)
    owout C.2,%1001,($CC,$44)
    owout C.3,%1001,($CC,$44)
    owout C.4,%1001,($CC,$44)
; send &#8216;reset&#8217; then &#8216;skip ROM&#8217;
; then &#8216;convert&#8217; then apply &#8216;pullup&#8217;
    pause 750 ; wait 750ms with strong pullup
    owout C.1,%0001,($CC,$BE)
    owout C.2,%0001,($CC,$BE)
    owout C.3,%0001,($CC,$BE)
    owout C.4,%0001,($CC,$BE)
; send &#8216;reset&#8217; then &#8216;skip ROM&#8217;
; then &#8216;read temp&#8217; command
    owin C.1,%0000,(b0,b1) ; read in result
    w0 = w0 / 16
    owin C.2,%0000,(b2,b3) ; read in result
    w1 = w1 / 16
    owin C.3,%0000,(b4,b5) ; read in result
    w2 = w2 / 16
    owin C.4,%0000,(b6,b7) ; read in result
    w3 = w3 / 16
    sertxd (#timer3," ",#w0," ",#w1," ",#w2," ",#w3,CR,LF) 
    pause 4000
  loop
(This was probably someone else's program, but I didn't note whose--sorry.)

The timings you mentioned above seem to be no finer than one second, so it looks to me like you might achieve what you want with 500ms "ticks". I will work on something, but might not be able to get it done before tomorrow evening.

Meanwhile, if you could provide meaningful names (with "symbol" statements) for the "b##" and "w##" variables you use in the program, it would help (and that would also make clear which additional variable were available to be used). (Note: I always avoid the use of b0 (and often b1, b2, and b3) because it contains named bits which can be used as flags to indicate certain events or program states.)
 
Last edited:

lbenson

Senior Member
Another snippet. This uses the x2 timer function to effectively produce a tick every half second. (The program uses the 20x2, which I had handy, but will also work with the 28x2.)
Code:
' 20timertest tests 500ms timing
#picaxe 20x2
#terminal 9600
#no_data
#no_table

  symbol bSecondFlag = bit2
  symbol wLastTimer = w27

setfreq M8
settimer t1s_4 ' timer variable ticks every half second (at M8)
wLastTimer=timer

main:
  do
    do while wLastTimer=timer : loop
    wLastTimer=timer ' reset
    inc bSecondFlag  ' toggles between 0 and 1
    if bSecondFlag = 1 then ' one second has elapsed
      high B.1
    else ' do things on the half-second (e.g. turn off camera
      low B.1
    endif
  loop
Note that the combination "setfreq M8 : settimer t1s_4" causes the special variable, "timer" to increment every 500 ms (with "m4" or "t1s_8" it would be every second).

The code checks for a change in the timer variable, toggles a bit with every change, and with the IF statement executes one section of code if the bit is 1, and the other section if the bit is 0, thus giving you different things you can do every half second. For this to work, neither section of code may run for more than 500ms, so the READTEMP command is out, and long PAUSE commands are out (your "PAUSE 10"s should be fine). You can use the OWIN/OWOUT commands to read the DS18B20s every second and restart the reads, thus getting around the READTEMP delays.

So using the bits in the program I previously submitted (bSnap and bVideo), when the video is not running, you could turn on the snapshot pin on the second, and turn it off on the half second.

Note further that any necessary pauses that you do retain, like the PAUSE 10 between eeprom writes, would need to be doubled to account for the M8 speed. Better, though, would be to combine all the eeprom log writes into a single write.

I will try to integrate everything, but it will probably be this evening or tomorrow morning before I can.
 
Last edited:

AllyCat

Senior Member
Hi,

I thought that your EEPROM memory chip was specified earlier in the thread, but I can't find it now. However, the largest that the AXE401 will accept (directly) is a 24LC512 which has 64k bytes. That equates to about 3 bytes/second for a 6 hour flight. You appear to be recording four values (two temperatures, battery voltage and light level) but the battery voltage and internal temperature are unlikely to change very rapidly. I'm surprised you're not measuring pressure (=~altitude) directly as the sensors are so cheap (at least if you're prepared to wait for them to come from China), but I haven't checked their typical minimum value.

However, I've been looking a little at the background to the project: Apparently the balloon is expected to reach between 15 and 30 km which in "old money" is 50,000 to 100,000 feet. The fall in temperature is about 1 degree C for each 500 feet, so it looks as if the temperature might fall by at least 100 C and maybe 200 C (from a ground level value of 30 C ? ).

The DS 18L20 is specified down to -55 degrees C, but it's not clear (at least to me) what happens below that. Being "digital", it might just limit at that value, but its data register has a 2^6 bit (plus a sign bit), so it might report down to -127 degrees (at reduced accuracy). Of course the PICaxe (and most other components) are not specified to work down there, but the internal temperature should remain (much?) higher. Therefore, I would be considering an (additional) analogue temperature sensor (with the PICaxe's ADC). The simplest is a forward diode (or a transistor Vbe) which has a tempco of around +2 mV for each degree C fall in temperature. It might not be particularly accurate, but may give some indication if you got to 15 km or 30 km. ;)

Cheers, Alan.
 

Etishere

New Member
Hi Ally Cat

Sorry, for the late reply, been busy with our project, see below, Tami and myself. Reading your post above, we are actually just installing the BMP280 Pressure & Altitude sensor now, I bought it some time ago, but we are only fitting it now, still need to work out the code for it.
We connected it to C.3 (SCL) and C.4 (SDA) do you know what other code we need to insert ? will check the picaxe manuals now.

We decided to buy a smaller chip an project board to run the camera and video separately on their own chip.
Sorry, no pictures now
Stephen
 

AllyCat

Senior Member
Hi,

Reading data via the I2C bus should be fairly easy, but the (accurate) mathematical calculation appears not to be. However, you might store the raw data and "post-process" the values after its return. There are several threads (at least for the BMP 180) on this forum, perhaps this is a good starting point. The forum search is just to the right of "Buy Now" at the top, but can be rather temperamental.

However, I see that the limit pressure / altitude (of the 180) is 300 hPa / 9,000 metres or ~30,000 feet. Again, it's not clear what happens if taken out-of-range, but if it uses a "sealed" micro-vessel filled with gas then there's a small risk that it might literally explode at high altitude. Looks like maybe a GPS is called for (there are also some threads on the forum), but hardly suitable for a 1 - 2 weeks timescale. :(

Cheers, Alan.
 

lbenson

Senior Member
With a new camera module, I'm not sure you're still interested in the same timing control. In any case, I think the following program mostly does what you had outlined before--LDR and battery readings every second, camera snapshot every second (adjustable), except when video is on (for example, for 20 seconds after a minute's worth of snapshots).

I used a 20X2 for testing, but it should work for a 28X2 with the "#define x20x2" statement commented out, as below.
Code:
' 20cubesat tests 500ms "tick" timing
'#define x20x2
#ifdef x20x2
  #picaxe 20x2 ' use 20x2 C.2,C.3 for ADC (Bat voltage & LDR)
#else
  #picaxe 28x2
#endif
#terminal 9600
#no_data
#no_table
#define testing 

'------------------------ Setup Symbols --------------------------
symbol pInsideTemp = C.0
symbol pOutsideTemp = C.1
symbol pFlight_Trigger=pinC.2

symbol cVideoMinutes = 1 ' video every n minutes
symbol cVideoLapsedTics = cVideoMinutes * 120 ' # ticks between videos
symbol cVideoNTicks = 20 '  video for n/2 seconds, e.g. 20/2=10sec

'symbol b0 reserved for bit flags
symbol bSnap = bit0
symbol bVideo = bit1
symbol bSecondFlag = bit2

symbol tempByte     = b1
symbol Counted_Logs =w1
symbol videoTicks   = b4
' symbol ??         = b6 ' reserved for Bat Volts conversion
' symbol ??         = b7 ' reserved for Bat Volts conversion
' symbol w??        = w4 ' b8&b9 reserved for Bat Volts conversion
' symbol w??        = w5 ' b10&b11 reserved for LDR conversion
  symbol Memory_Add_I =w6
  symbol Memory_Add_O =w7
  symbol Char1=b16
  symbol Log_Time =w10
  symbol Log_T =w11
  symbol Log_Counter =w12
symbol insideTemp  = b26
symbol outsideTemp = b27


symbol wTemp       = w24 ' b48 and b49
symbol wStartVideo = w25
symbol wTickCount  = w26
symbol wLastTimer  = w27

   '------------------------ Setup Counters -------------------------
   Log_Counter=600 'The number of logs to make during flight (NB max of 8000 
                  ' readings for 512KBit's Memoru chip 24LC512) 
   Log_Time=0 '# The time between logs In seconds up op 65535 (NB 0=1Sec ans 1=2Sec)

owout C.0,%1001,($CC,$44) ' initiate one-wire temperature read
owout C.1,%1001,($CC,$44)
pause 1000 ' initial allowance of DS18B20 time to settle

setfreq M8
pause 2000 ' settle time for sertxd after M8
sertxd("Flight_Pin=",#pFlight_Trigger,cr,lf)
settimer t1s_4 ' timer variable ticks every half second (at M8)
wLastTimer=timer

main:
  do
    do while wLastTimer=timer : loop
    wLastTimer=timer ' reset
    gosub Camera
    wStartVideo = timer // cVideoLapsedTics ' e.g., every 5 minutes (2 ticks * 60 seconds * 5 minutes)
    if bvideo = 1 or wStartVideo = 0 or wStartVideo = 1 then gosub Video ' (don't mis-align ticks)

    inc bSecondFlag  ' bitflag toggles between 0 and 1
    if bSecondFlag = 1 then ' one second has elapsed
      high B.1
      GoSub readTemps
      GoSub Battry_Voltage
      GoSub Read_LDR
      Gosub Check_Flight_Pin
    else ' do things on the half-second (e.g. turn off camera
      low B.1
    endif
  loop

Camera: ' this will result in a snapshot every second if video is not recording
  if bVideo = 0 then ' OK to snap or terminate snap
    if bSnap = 0 then ' start snap
      high B.5 'Camera On
      bSnap = 1
    else
      low B.5 'Camera Off
      bSnap = 0
    endif
  endif
  return

Video: ' this will result in a 10 second video if snapshot not in progress
  if bSnap = 0 then ' ok to start or stop video
    if bVideo = 0 then ' start video
      high B.7 'Video On
      bVideo = 1
      videoTicks = 0
    else
      inc videoTicks
      if videoTicks >= cVideoNTicks then
        low B.7 'Video Off
        bVideo = 0
      endif
    endif
  endif
  return

readTemps:
; send &#8216;reset&#8217; then &#8216;skip ROM&#8217;
; then &#8216;convert&#8217; then apply &#8216;pullup&#8217;
    owout C.0,%0001,($CC,$BE)
    owout C.1,%0001,($CC,$BE)
    owin C.0,%0000,(b48,b49) ; read in result
    wTemp = wTemp / 16
    insideTemp = b48
    owin C.1,%0000,(b48,b49) ; read in result
    wTemp = wTemp / 16
    outsideTemp = b48
#ifdef testing
    sertxd("in=",#insideTemp,"; out=",#outsideTemp," ")
#endif

    owout C.0,%1001,($CC,$44) ' re-initiate one-wire temperature read
    owout C.1,%1001,($CC,$44)
    return

'---------------------------Batary Voltage monitor--------------------
Battry_Voltage:
#ifdef x20x2
   readadc C.3, W4
#else
   readadc A.0, W4
#endif
   w4 = w4 * 40/100 'Scale/MAP 40/100
   bintoascii W4,b6,b6,b6,b6,b7 
#ifdef testing
   sertxd(#b6,".",#b7,"V, ")
#endif
   return

'----------------------------LDR Light intensity----------------------
Read_LDR:
#ifdef x20x2
   readadc C.7, W5
#else
   readadc A.1, W5
#endif
   'bintoascii W5,b18,b18,b18,b18,b19
#ifdef testing
   sertxd("LDR=",#w5,cr,lf)
#endif
   return

'----------------------------Disply on PC While Flight pin In---------
PC_Disply:
  sertxd (" ",b6,",",b7,"V")
  sertxd (" LDR ",#w5," ")
  tempByte = insideTemp
  if tempByte > 127 then
    let tempByte = tempByte - 128
    sertxd (" I-Temp -",#tempByte," ")
  else
    sertxd (" I-Temp ",#tempByte," ")
  end if

 '------------------------
  tempByte = outsideTemp
  if tempByte > 127 then
    let tempByte = tempByte - 128
    sertxd (" E-Temp -",#tempByte,cr,lf)
  else
    sertxd (" E-Temp ",#tempByte,cr,lf)
  end if
  
  return

Check_Flight_Pin:
 'Is the Flight Pin Pulled Yes/No
  if pFlight_Trigger=1 then
    'Yes
    if log_Time <log_T then
      GoSub Data_To_Memmory
      Log_T=0
    endif 
  else 
    'No
    GoSub PC_Disply 
  end if
   '-------------------
  high B.1
  pause 10'450
  Log_T=Log_T+1
  sertxd (#log_T," ")
  return

  
'============================= Data to Memory =============================
Data_To_Memmory:
  read 0,WORD Memory_Add_I
'  read 1,b13
  'sertxd ("Mem Add ",#W6,cr,lf)
  
  if Log_Counter = Counted_Logs Then ' blink forever
    sertxd (cr,lf,"Log_Counter = Counted_Logs ",#Counted_Logs," ")
'    for tempbyte = 1 to 20 :toggle B.1 : pause 400 : next ' 200 ms @ M8
    do :toggle B.1 : pause 400 : loop ' 200 ms @ M8
  else
    ' Increment log counter---------------------------------------------
    Counted_Logs=Counted_Logs+1
    sertxd (cr,lf,"Writing record ",#Counted_Logs," ")
    '-------------------------------------------------------------------
    'Write Start Byt to i2cEEPROM -------------------------------------------
  
 #ifndef x20x2 
    writei2c Memory_Add_I,("#") ' Start marker 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    'Write Battart voltage to i2cEEPROM -------------------------------
  
    writei2c Memory_Add_I,(b6) ' write the Volt record to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    writei2c Memory_Add_I,(b7) ' write the Milie Volt record to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    'Write LDR to i2cEEPROM -------------------------------------------
  
    writei2c Memory_Add_I,(b10) ' write LDR record to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    writei2c Memory_Add_I,(b11) ' write the LDR record to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    'Write Internal Tempratur to i2cEEPROM----------------------------------
  
    writei2c Memory_Add_I,(b24) ' Internal Tempratur to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
    'Write Ecternal Tempratur to i2cEEPROM----------------------------------
  
    writei2c Memory_Add_I,(b26) ' Ecternal Tempratur to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
  
  
    'Write Stop Byt to i2cEEPROM -------------------------------------------
  
    writei2c Memory_Add_I,("; ") ' write LDR record to memory 
    pause 10 ' wait 10 ms for write
    Memory_Add_I=Memory_Add_I+1
 #endif
  
    'Store Memory Counter
    write 0,WORD Memory_Add_I
'    write 1,b13
   'Store counted logs
    write 2,WORD Counted_Logs
 '   write 3,b3
  end if
  return
This uses mostly your code except for the timing. The main loop executes every half second. A flag, bSecondFlag, becomes "1" once a second, and most of the code is executed when that happens (other "tick" times could be calculated with, for instance "2seconds = timer // 4 : if 2seconds = 0 then " or "4seconds = timer // 8 : if 4seconds = 0 then ").

I didn't have an eeprom connected, so that part of the code is not tested, but should, unless I misunderstood, run as your previous code did.

The timer will overflow after 65536 half seconds, but that's over 9 hours, so for your flight, it shouldn't matter (and might not anyway).

I did some reorganizing. One change I made throughout--when you write to or read from the internal eeprom with the two b## variables of a word, I changed it to use the "WORD" qualifier, for instance, instead of "write 2,b2 : write 3,b3" I put "write 2, WORD Counted_Logs".

Hope this is of some use.

[More code follows.]
 

lbenson

Senior Member
Because of forum text length limitations, I had to omit two initialization routines from the end of the program. Here they are:
Code:
   '----------------------- Setup EEPROM -----------------------------
SetupEEPROM: ' initialize
  hi2csetup i2cmaster, %10100000, i2cfast, i2cword
   'Is the Flight Pin Pulled Yes/No
  if pFlight_Trigger=1 then
    'Yes (continue)
    '------------------ Record Count full Yes/No -----------------------
    'read counted logs
    read 2,WORD Counted_Logs
'    read 3,b3
    '------------------
    if Counted_Logs=Log_Counter then
    'Yes
      gosub Read_Memory
      else 
   'No
  
    end if
  else 
   'No 
   '-----Set i2cEEPROM Add to 0----
    Memory_Add_I=0
    write 0,WORD Memory_Add_I
  
    Counted_Logs=0
    write 2,WORD Counted_Logs
'    write 3,b3
  
    sertxd (cr,lf," @@@@@@@@@@@@ Memory Reset @@@@@@@@@@ ",cr,lf)
    Log_T =0
    '-------------------------------
  end if
  return 

Read_Memory:
  sertxd (cr,lf,"##################### READING MEMORY ##################",cr,lf)
  'Read last Addres
  read 0,WORD Memory_Add_I
'  read 1,b13
  sertxd ("End Addres= ",#Memory_Add_I,cr,lf) 
  For Memory_Add_O=0 to Memory_Add_I
    high B.1
    'Start byt
    pause 10 ' wait 10 ms for write
    readi2c Memory_Add_O,(Char1)
    pause 10 ' wait 10 ms for write
    sertxd (Char1," ")
    pause 10
    Memory_Add_O=Memory_Add_O+1
    'Voltage
    readi2c Memory_Add_O,(Char1)
    pause 10 ' wait 10 ms for write
    sertxd (Char1,",")
    pause 10
    Memory_Add_O=Memory_Add_O+1
    'Millie Voltage
    readi2c Memory_Add_O,(Char1)
    pause 10 ' wait 10 ms for write
    sertxd (Char1,"V ")
    pause 10
    Memory_Add_O=Memory_Add_O+1
    'LDR 
    readi2c Memory_Add_O,(b4)
    pause 10 ' wait 10 ms for write
    Memory_Add_O=Memory_Add_O+1
    readi2c Memory_Add_O,(b5)
    pause 10 ' wait 10 ms for write
    Memory_Add_O=Memory_Add_O+1
    sertxd ("Light_Intencity=",#W2,",")
    pause 10
  
    'Internal Tempratur
    readi2c Memory_Add_O,(b4)
    pause 10 ' wait 10 ms for write
    Memory_Add_O=Memory_Add_O+1
  
    if b4 > 127 then
      let b25 = b4 - 128
      sertxd (" Inside_Cube-Temperature -",#b25," ")
    else
      sertxd (" Inside_Cube-Temperature ",#b4," ")
    end if
    '---------LED Off-----------
    low B.1 
    'External Tempratur
    readi2c Memory_Add_O,(b4)
    pause 10 ' wait 10 ms for write
    Memory_Add_O=Memory_Add_O+1
  
    if b4 > 127 then
      let b27 = b4 - 128
      sertxd (" Outside-Temperature -",#b27," ")
    else
      sertxd (" Outside-Temperature ",#b4," ")
    end if
  
    'Stop Byt
    readi2c Memory_Add_O,(Char1)
    pause 10 ' wait 10 ms for write
    sertxd (Char1,cr,lf)
    pause 10
  
  Next Memory_Add_O
  return
The one-wire commands, OWIN and OWOUT, work as expected to take temperature readings from as many DS18B20 sensors as you want every second.

I mapped some sensors to different locations for the 20X2, but also used #define statements so your original ports should be correct for the 28X2.
 

srnet

Senior Member

AllyCat

Senior Member
Hi,

... we are actually just installing the BMP280 Pressure & Altitude sensor now, I bought it some time ago, but we are only fitting it now, still need to work out the code for it.
It's probably worth starting a new thread, perhaps titled "Using the BMP 280 at high altitudes", to avoid the details in this thread becoming too "interleaved". The flight gives a great opportunity to test how these sensors (and the 18B20) behave when "out of their comfort zone". So, even without your tight deadline, it would make sense to record the "raw" temperature and pressure data and post-process with a PICaxe, or a spreadsheet program, after the event. Of course you should record the calibration data before the flight, in case the sensor gets "broken".

IMHO the calculations are within the capability of a PICaxe (without the need to write a new operating system or maths package) but probably not to be developed, debugged and verified within less than two weeks! Personally, I only have a BMP180 board and haven't yet attempted to write a program to use it.

I doubt if your temperature or pressure data will change very rapidly (except perhaps during a parachute descent), so I'd be inclined to record more data "channels", but less frequently than a once per second. The only value which might vary rapidly is the LDR, if the "cube" is spinning or tumbling.

It's worth looking at the BMP180 data sheet as well as the 280 (which looks rather like "overkill" for your requirements) because it's simpler, but includes a formula to convert pressure to altitude. I did a quick "sanity check" and it indicates that if you did reach 30 km (!00,000 feet) and everything kept working, then the air pressure should be only around 25 hPa, or 2.5% of ground level pressure.

Cheers, Alan.
 

Etishere

New Member
Hi Alan / Benson

Thanks for the update, we sat for most of Saturday night, till midnight, can't get this stupid BMP280 sensor to do anything, seems I'm not alone though, the main rocket scientists that are flying the main balloon couldn't get it write either.
Anyways, that's something for another day, for now, it will just look pretty and show "Altitude 0" all the way....

Tonight I'm still working on the code for the camera / video inclusion in the main code, Willie "Our number one "Rocket Scientist" and I'm not bashing Willie' Willie and Christo, the REAL Scientist, this is their project. Willie said I should add the code at the end of the program / after the end, its kinda working like that, the camera took 723 snaps in 10 mins :confused:
and 53 odd video clips, some very very short but of cause due to the "WAIT 10000" and PAUSE 5 commands, this makes the rest of the program very slow.
I may be able to live with that though.
So we are now working on speeding up that process.

Cheers
Stephen
 

AllyCat

Senior Member
Hi,

"A picture is worth 1000 words" so that's obviously the first thing to get working. But it shouldn't be difficult to "interleave" a snapshot between each Data measurement (or vice versa). A one second cycle seems rather fast, have you calculated the maximum number of data blocks and photos that your hardware can accept (in 20,000 seconds)? Then write two separate subroutines for "Start Video" and "Stop Video" and interleave (time share) those with the snapshots.

However, this seems a great opportunity to get some "raw" pressure/temperature data which could be decoded later. In most respects the BMP280 looks like "overkill", but I do see that its data sheet does specify the absolute minimum pressure as "zero", whilst it's not defined for the BMP180. It shouldn't be too difficult to get some data via the I2C interface, but a few things must be "right". I presume you're using a "Breakout" module, but there do appear to be a few "options" that need checking: It has two power supply pins (analogue and digital); CSB must be connected "High" and SDO must be connected (either High or Low).

The slave address appears to be $EC or $EE , then you should be able to read the "Device ID" ($58) from register $D0. Then read the 26 calibration bytes from registers $88 to $A1, which only needs to be done once, not necessarily in the "flight" software. The flight program only needs to read registers $F7 to $FC as a single burst. These data bytes could be "compressed" before writing to EEPROM, but it would be simpler/safer just to record them less frequently, perhaps once with each Video?

Post any code that doesn't work as expected/intended and we might be able to help.

Cheers, Alan.
 

Etishere

New Member
Morning Alan

Thanks, I'm at work now, this BMP280 sensor, how I have it wired up is:
Power VCC 3.3 v and ground, connected directly to the PIC 401 board shield.
Then SCL connected directly to PIN C.3 and SDA to PIN C.4, I'm not usig any other "Breakout" board in between the sensor and the PIC, didn't know I had to.
Maybe that's my problem.

So if its simple enough to write some lines of code to read directly from the sensor ??? please, I'd like some code, if not, then I'll fly the sensor for show this time round.

Enjoy your day

Stephen
 

AllyCat

Senior Member
Hi Stephen,

The "BMP280" is actually a tiny Surface Mount package, only just over 2mm square with 8 "pins", which are almost impossible to hand-solder, even for an expert. So they are usually sold in a module, with pads having a 0.1 inch (2.5mm) pin spacing, sometimes called a "breakout" board. That board may also carry other components such as the supply decoupling capacitor(s) and I2C pullup resistors, etc..

A problem can be that the breakout circuit diagram is often not available, particularly if the basic chip has several modes, like the BMP280 with its options of I2C and SPI data buses. Sometimes it's necessary to "reverse engineer" the "library" code intended for an Arduino.

Below are the two sides of a typical BMP280 module, which looks as if it should be possible to trace all the connections, but I won't bother unless that's exactly what you have. The two "extra" pins presumably determine the I2C/SPI mode and the I2C Slave address, which will determine whether the BMP280 "works" at all.

BMP280breakouta.jpg

Obviously the first test is to try to read some data from the chip that isn't $00 or $FF. I don't have a chip to try but suggest something like:

Code:
do
 PAUSE 1000

 HI2CSETUP I2CMASTER, $EC, I2CSLOW, I2CBYTE
 HI2CIN $D0,(b1)
 SERTXD(cr,lf,"Slave Address EC = ",#b1)   ; Device ID = 88 ?
 
 HI2CSETUP I2CMASTER, $EE, I2CSLOW, I2CBYTE
 HI2CIN $D0,(b1)
 SERTXD(cr,lf,"Slave Address EE = ",#b1)
loop
If one of those addresses works, you can try reading the configuration bytes ($8B upwards) and then live pressure/temperature bytes ($F7 to $FC). This might need : HI2COUT $F4,($01) to start conversion, then : PAUSE 10 : HI2CIN $F7,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr) since you might be running out of variables.

Cheers, Alan.
 
Last edited:

StefanST

New Member
Hi Stephen,

I would like to send a few questions, comments and suggestions to your project.

(1) Can you publish last version of the software?
(2) Can you publish last version of the hardware schema?
(3) What is your role in this project - can you change the program code of the main program loop - if it's not your code? Or just "add some code" to control the camera and video?

To the camera and video control:
(4) Have you adopted some of the lbenson's code (to use timer instead of the pause command for timing)? It is the best solution, if you have time to do it.

... I should add the code at the end of the program ... the camera took 723 snaps in 10 mins ...
(5) If you don't use timer, as proposed lbenson, you can "add the code at the end of the program". You can add camera_on and camera_off commands in the end of the main loop:
Code:
 high B.1
;    pause 10'450
    Log_T=Log_T+1
    sertxd (#log_T," ")
	high B.5    'Camera On
	pause 250
	low B.5    'Camera Off
    'debug
goto main
If the main loop will be too slow, you can exclude the 10ms pauses in the "Data_To_Memmory" procedure and exclude (comment out) the sertxd commands at the flight time. Who will read those messages at the fly?

(6) Question: Is it correct "high B.5 'Camera On" and "low B.5 'Camera Off"? Your reference in #13
at "https://www.rcgroups.com/forums/show...amera-R-C-hack" write: "white: +3.3v nominal, pull to ground for 250ms to take a still photograph".

(7) Have you calculated how many pictures and how much video-time you can store on your memory card?
I suppouse, you should store about 21,600 pictures (at rate 1picture/sec -> 6hours x 60min x 60sec). If your toy-camera needs 300kB(?) for one picture, then 21600 x 0.3MB = 6.5GB only for pictures. I do not know how much you need for video (about 10sec for every one minute => 6hod x 60 min x 10sec => 1hour of the continuos video record).

(8) Did you really tested if the memory card and battery are sufficient for this amount of the data?

- About the video recording:
(9) When recording the camera, you will receive approximately 14,000 to 21,000 images for about 4 to 6 hours. When playing these images at 30 frames per second, you'll have 7.5 to 11.5 minutes of an impressive video (at 10frames/sec it is 3 times more).

(10) Question: Why do you want to record a fragmentary video? For recording 10 seconds / 50 seconds pause, the entire record will take 40 to 60 minutes. It's too long for a regular observer. Except when the record is for scientific purposes.

(11) So my suggestion is: Do not create a video but just create a sequence of pictures only. You get a video from an image sequence. This sequence will then be continuous and will not be interrupted by the holes in the recording because the video does not allow simultaneous image capture.

(12) Clock:
- do you have: internal resonator or external X-tal?
- can you estimate or do you have measured frequency change in range of -40°C .. +20°C (1% / 10% / more?)
- the frequency change affects the 1 second reference and thus also the estimated time of measurement (if you assign the measurement time to the individual data records)

(13) Timing:
-> duration of the trip: 4-6hour
- time interval of the measurement: 1sec / 10sec ?
- you need to store the number of the data records (loops): total_flight_time / time_interval = 6hod / 1sec = 21600 records
- data_record_size = (start-temp1-temp2-light-bat_voltage-stop)=1+1+1+2+1+2 [byte]=8byte

- EEPROM 64kx8bit -> 64kB / 8byte = 8000 records -> sufficient for 2,2 hour @ 1sec interval !!!!
- EEPROM 64kx8bit -> 64kB / 8byte = 8000 records -> sufficient for 22 hour @ 10sec interval !!!!
=> WHAT TO DO WITH THIS?

(14) Others:
- Have you tested the electronics (battery capacity - other measurements - data storage) at low temperatures (-10°C .. -40°C)?
- Is the light measurement range sufficient with 8-bit resolution?
- Are there used any filters to light intensity measurement? (visible range, UV range)?

(15) Latest questions:
- How is measured battery voltage? I do not see any ADC initialization in your code.
- Why do you don't use readAdc10 command to measure battery and LDR? ReadAdc has a resolution of 256 levels, readAdc10 has 1024 levels.


** Because you do not have much time, I do not expect you to modify the program too much or modify it to more modular or more transparent. You probably just do tests whether the cube is doing what you expect. (Although the discussed pressure sensor would help in interpreting the data obtained.)

I wish you a successful flight.
 
Last edited:

AllyCat

Senior Member
Hi,

This might need : HI2COUT $F4,($01) to start conversion...
Just a brief update/correction: The "control" byte has the option to skip the measurement of temperature or pressure (or both !) so the "start" command needs to use hi2cout $F4,($25) to start conversion of both (with no oversampling). Therefore a simple program to measure the "Raw" values of Pressure and Temperature is:

Code:
 	hi2csetup i2cmaster,$EC,i2cslow,i2cbyte		; BMP280 address	
	hi2cout $F4,(%00100101)  		   	; Forced mode, no oversampling
	pause 10					; Allow conversion time to complete
	hi2cin $F7,(b1,b0,b4,b3,b2,b5)			; Read raw pressure and temperature data
	sertxd("T= ",#w1," P= ",#w0," os= ",#w2,cr,lf)
The breakout board/module that I pictured above defaults to I2C mode with address $FC if the CSB and SDO pins are not connected. Note that these chips have an Absolute Maximum supply voltage rating of 4.25 volts, but the board does not include a voltage regulator (unlike the BMP180 which it is said to "replace").

There are a few other "gotchas", the EPROM calibration words are stored LSByte first (like a PICaxe, but unlike the BMP180) but the Raw output data is MSByte first! However, the main gotcha is the very complex mathematical post-processing that is needed to give calibrated results. Here is some code that should read and display the calibration register values:

Code:
	hi2csetup i2cmaster,$EC,i2cslow,i2cbyte 		; BMP280 address
	hi2cin $D0,(b1)						; read sensor id
	sertxd(cr,lf,"ID= ",#b1,cr,lf)
	bptr = $88	
	hi2cin bptr,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc)
	hi2cin bptr,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc)
	hi2cin bptr,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc)	
	for bptr = $88 to $9F
	  w1 = @bptrinc
	  w1 = @bptr * 256 + w1 			; EPROM data is LSB first in 280 !
	  if bptr <> $89 and bptr <> $8F then			; Convert the "Signed" values
		if w1 > 32767 then
			w1 = -w1
	  		sertxd("-")
	  	endif	
	  endif  
	  sertxd(#w1,cr,lf)
	next bptr
Cheers, Alan.
 
Last edited:

Etishere

New Member
Hi everyone, that's been helping...
Sorry I haven't been back for a while, its been really hectic my side, 3 days to the launch.
Well the team decided to get another pic, its a 20M2, then we programmed that PIC to only run the camera, it will take 2 snaps per minute and one video every minute lasting 22 seconds.
that equates to approx. 68 Meg per video file. we fitted a 32 GB SD Card last night - sorted.

Then the PIC 28X2 will only run the original sensors, we were getting lots of garbage our on replaying the logged data, it seams to log the data Ok, but when we retrieve it, whe readings don't make sense, we also failed to get the BMP280 sensor to show any meaningful info.

So the PIC are programmed and ready to fly, we are busy wiring in the cross band repeater and dorji radio for aprs tracking now and a second radio module for aprs and a cw beacon for the 2nd cube.
Will give everyone feedback if we recover our cubes.

thanks again
Stephen
 

AllyCat

Senior Member
Hi,

we were getting lots of garbage our on replaying the logged data, it seams to log the data Ok, but when we retrieve it, whe readings don't make sense, we also failed to get the BMP280 sensor to show any meaningful info.
Thanks for the update. It's a pity you didn't get the BMP280 working; it doesn't seem too difficult to get some "raw" data output (the mathematical post-processing is another matter), but IMHO the "replaces BMP180" in ebay listings is rather misleading.

As for the data corruption, I've just noticed a writei2c Memory_Add_I,("; ") ' write LDR record to memory in the early version of you program. That would write two bytes into the EEPROM, but the I2C devices are normally organised with internal "blocks" of bytes, so a common "gotcha" is for multiple written bytes to wrap around within the block. :(

Cheers, Alan.
 
Top