DRPlayer with 08M2 chip

regpye

New Member
but you'll have to wait for that episode to arrive.
Sounds like a good episode coming up again.
I think maybe it would be also wise to make the sleep come into play when the LDR <90 so that it is actually very dark, maybe even a lower value.
 

regpye

New Member
I would have edited the main loop and added some more routines ...
Ideally the fade in should be on the first file and the first instance of the second file, but repeating second files would sound better if a continuance of the same volume with no fading at either end, but maybe that is too hard to implement?
 

hippy

Ex-Staff (retired)
Ideally the fade in should be on the first file and the first instance of the second file, but repeating second files would sound better if a continuance of the same volume with no fading at either end, but maybe that is too hard to implement?
It should be reasonably easy to change the main loop to do anything you want; it's just a question of choosing the right sequence.

With what was proposed, track two should fade in after track one, and when track two reaches its end, it should repeat at full volume, with no fading,, until dusk when it does fade out and then remains silent until dawn. If you edited the actual track to fade in then that's what you will be hearing.

Fading in track one and track two is easy enough with software, as is fading out track two when dusk arrives. But fading out track one before fading in track two the first time is a little challenging.

Putting the fade out in track one itself means the code knows it will have faded out when the track has ended so it only has to then fade in track two.

If track one doesn't itself fade out the code will need to know how long the track is, how long it should run for before fading it out, stopping it and fading in track two.
 

regpye

New Member
Fading in track one and track two is easy enough with software, as is fading out track two when dusk arrives. But fading out track one before fading in track two the first time is a little challenging.
It is easy to prepare the files to what ever length is needed with or without fade at either end. Ideally though, files that are un-faded and controlled by the code would be a better option I think. If coding is hard to do for either type of fading, it can be done in the file itself.
Although this started out as a simple project, I have learnt so much so far, different methods of doing things and many different techniques that I never would have thought of.
 

hippy

Ex-Staff (retired)
If it's easy enough to add the fade out to track one that would make the code easier -
Code:
  Do
    Gosub WaitForDawn
    ; Track 1 - Software fade-in, fade-out in track itself 
    Gosub SetVolumeToOff
    Gosub PlayFirstTrack
    Gosub FadeUpVolume
    Gosub WaitForTrackToEnd
    ; Track 2 - Software fade-in, repeat without fading, software fade-out at dusk
    Gosub SetVolumeToOff
    Gosub PlaySecondTrackWithRepeat
    Gosub FadeUpVolume
    Gosub WaitForDusk
    Gosub FadeDownVolume
    Gosub StopTrack
  Loop
 
Last edited:

hippy

Ex-Staff (retired)
Here's how I would add false dusk and dawn detection, untested -

Edit : Corrected code using 'SLEEP_SECS' and 'SLEEP_UNITS'
Edit : Refactored code to be more logical
Code:
; We only need to sleep for short periods during the day as
; the battery should be recharging. At night time we sleep
; for a longer period.
;
; Though each 'sleep' unit is about 2.3 seconds we will
; pretend it's a round 2 seconds. It might actually be one 
; to four seconds but it doesn't really matter if we are a 
; few minutes sooner or later in detecting dawn or dusk.

Symbol SLEEP_SECS_DURING_DAY   = 2 ; Multiples of 2 and 2 minimum
Symbol SLEEP_SECS_AT_NIGHT     = 8 ; Multiples of 2 and 2 minimum

Symbol SLEEP_UNITS_DURING_DAY  = SLEEP_SECS_DURING_DAY / 2
Symbol SLEEP_UNITS_AT_NIGHT    = SLEEP_SECS_AT_NIGHT   / 2

; If we get a dawn or dusk which lasts this long we consider
; it to be a fact. Any dusk or dawn which is shorter we can
; consider a 'false dawn' or 'false dusk' and ignore that.

Symbol DAWN_PERIOD_SECS        = 300 ; 300 secs = 5 minutes
Symbol DUSK_PERIOD_SECS        = 300 ; 300 secs = 5 minutes

; Keep track of how long we have detected a continuous dawn
; or dusk for.
  
Symbol secondsCounter          = w3 ; b7:b6
Code:
WaitForDawn:
  secondsCounter = 0
  Do
    ; We are waiting for dawn so can presume we are running
    ; at night time
    Sleep SLEEP_UNITS_AT_NIGHT
    Gosub ReadTheLdrLevel
    If ldrLevel > LDR_LEVEL_AT_DAWN Then
      ; It is potentially dawn, so we count how long dawn seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_AT_NIGHT
    Else
      ; It is not dawn so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dawn, not a false dawn, then
    ; we return, otherwise keep going round the loop until it is
    ; dawn
  Loop Until secondsCounter >= DAWN_PERIOD_SECS
  Return
Code:
WaitForDusk:
  secondsCounter = 0
  Do
    ; We are waiting for dusk so can presume we are running
    ; during the day
    Sleep SLEEP_UNITS_DURING_DAY
    Gosub ReadTheLdrLevel
    If ldrLevel < LDR_LEVEL_AT_DUSK Then
      ; It is potentially dusk, so we count how long dusk seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_DURING_DAY
    Else
      ; It is not dusk so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dusk, not a false dusk, then
    ; we return, otherwise keep going round the loop until it is
    ; dusk
  Loop Until secondsCounter >= DUSK_PERIOD_SECS
  Return


I think maybe it would be also wise to make the sleep come into play when the LDR <90 so that it is actually very dark, maybe even a lower value.
The advantage of defining and using 'LDR_LEVEL_AT_DAWN' and 'LDR_LEVEL_AT_DUSK' is that it's easy to change those values at the top of the program while experimenting with prototype code to see what the best values are.

There will usually be some tuning required to get 'should be good enough to start with' values better.
 
Last edited:

regpye

New Member
Do Gosub WaitForDawn ; Track 1 - Software fade-in, fade-out in track itself Gosub SetVolumeToOff Gosub PlayFirstTrack Gosub FadeUpVolume Gosub WaitForTrackToEnd ; Track 2 - Software fade-in, repeat without fading, software fade-out at dusk Gosub SetVolumeToOff Gosub PlaySecondTrackWithRepeat Gosub FadeUpTrack Gosub WaitForDusk Gosub FadeDownVolume Gosub StopTrack Loop
FadeUpVolume FadeUpTrack
Are these both doing the same job?
There is no FadeUpTrack code in your example.
Is it just a repeat in a different position?
 

hippy

Ex-Staff (retired)
FadeUpVolume FadeUpTrack
Sorry, simple typo from typing directly into the forum. It was meant to be 'FadeUpVolume'. Corrected the original post.

Also corrected code for false dawn and dusk filtering to remove a timing bug, thinking units of sleep was the time of that sleep when it's not.
 

regpye

New Member
Sorry, simple typo from typing directly into the forum
Easy done, I am guilty myself of that a few times.
Thanks for all your coding Hippy, I have learnt a lot with this project.
I will build another circuit up and test it out soon, the first circuit has been given away to a friend that wanted it after hearing the birds singing (and squawking) in my backyard.
 

regpye

New Member
I have a circuit board which is really over kill for this project as it is a 20M2 board with a DFPlayer built in and several inputs and mosfet outputs.
It is only a temporary use for this code for testing as I haven't had time to build another 08M2 board yet.
I have modified both the codes below to suit a 20M2 chip instead of a 08M2
I tired is code that I have put together from Hippy's last coding and it is not functioning., maybe I have done something stupid again.

Code:
#No_Data

; Define hardware

Symbol LDR                = C.7
Symbol TX                 = C.0
Symbol Busy_Pin           = PinB.5
Symbol LDR_LEVEL_AT_DAWN  = 105      ; LDR reads higher than this during the day
Symbol LDR_LEVEL_AT_DUSK  =  95      ; LDR reads less than this at night

Symbol BAUD_FREQ          = M8
Symbol BAUD               = T9600_8

Symbol MP3_PLAY          = $12     ; play track
Symbol MP3_REPEAT_PLAY    = $08      ; Repeat play a track
Symbol MP3_STOP           = $16      ; Stop track playing
Symbol MP3_SET_VOLUME     = $06      ; Set the volume

Symbol MAX_VOLUME         = $1E      ; Max volume level, $1E = 30

; Variables

Symbol cmd                = b0
Symbol arg                = w1 ; b3:b2
Symbol arg.lsb            = b2
Symbol arg.msb            = b3

Symbol ldrLevel           = b4
Symbol Busy_Delay = 2000  ; Change Busy delay value here
; We only need to sleep for short periods during the day as
; the battery should be recharging. At night time we sleep
; for a longer period.
;
; Though each 'sleep' unit is about 2.3 seconds we will
; pretend it's a round 2 seconds. It might actually be one 
; to four seconds but it doesn't really matter if we are a 
; few minutes sooner or later in detecting dawn or dusk.

Symbol SLEEP_SECS_DURING_DAY   = 2 ; Multiples of 2 and 2 minimum
Symbol SLEEP_SECS_AT_NIGHT     = 8 ; Multiples of 2 and 2 minimum

Symbol SLEEP_UNITS_DURING_DAY  = SLEEP_SECS_DURING_DAY / 2
Symbol SLEEP_UNITS_AT_NIGHT    = SLEEP_SECS_AT_NIGHT   / 2

; If we get a dawn or dusk which lasts this long we consider
; it to be a fact. Any dusk or dawn which is shorter we can
; consider a 'false dawn' or 'false dusk' and ignore that.

Symbol DAWN_PERIOD_SECS        = 300 ; 300 secs = 5 minutes
Symbol DUSK_PERIOD_SECS        = 300 ; 300 secs = 5 minutes

; Keep track of how long we have detected a continuous dawn
; or dusk for.
  
Symbol secondsCounter          = w3 ; b7:b6

; Main program


PowerOnReset:
  High TX

  Do
    Gosub WaitForDawn
    ; Track 1 - Software fade-in, fade-out in track itself 
    Gosub SetVolumeToOff
    Gosub PlayFirstTrack
    Gosub FadeUpVolume
    Gosub WaitForTrackToEnd
    ; Track 2 - Software fade-in, repeat without fading, software fade-out at dusk
    Gosub SetVolumeToOff
    Gosub PlaySecondTrackWithRepeat
    Gosub FadeUpVolume
    Gosub WaitForDusk
    Gosub FadeDownVolume
    Gosub StopTrack
  Loop
; Day and night handling

WaitForDawn:
  secondsCounter = 0
  Do
    ; We are waiting for dawn so can presume we are running
    ; at night time
    Sleep SLEEP_UNITS_AT_NIGHT
    Gosub ReadTheLdrLevel
    If ldrLevel > LDR_LEVEL_AT_DAWN Then
      ; It is potentially dawn, so we count how long dawn seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_AT_NIGHT
    Else
      ; It is not dawn so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dawn, not a false dawn, then
    ; we return, otherwise keep going round the loop until it is
    ; dawn
  Loop Until secondsCounter >= DAWN_PERIOD_SECS
  Return

WaitForDusk:
  secondsCounter = 0
  Do
    ; We are waiting for dusk so can presume we are running
    ; during the day
    Sleep SLEEP_UNITS_DURING_DAY
    Gosub ReadTheLdrLevel
    If ldrLevel < LDR_LEVEL_AT_DUSK Then
      ; It is potentially dusk, so we count how long dusk seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_DURING_DAY
    Else
      ; It is not dusk so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dusk, not a false dusk, then
    ; we return, otherwise keep going round the loop until it is
    ; dusk
  Loop Until secondsCounter >= DUSK_PERIOD_SECS
  Return
  
SleepForSomeTime:
  Sleep 1 ; Doesn't really matter how long we sleep for at this stage
  Return

ReadTheLdrLevel:
  ReadAdc LDR, ldrLevel
  Return
  
PlayFirstTrack: ; Handle track playing
cmd = MP3_PLAY : arg = 0001 : Gosub Send ;
;gosub WaitForTrackToEnd
 Return
 

PlaySecondTrackWithRepeat:
  cmd = MP3_REPEAT_PLAY : arg = 0002 : Gosub Send ; Repeat track '/MP3/0002.mp3'
  Return

StopTrack:
  cmd = MP3_STOP : arg = 0 : Gosub Send ; Stop playing track
  Return

; Handle volume control

SetVolumeToFull:
  cmd = MP3_SET_VOLUME : arg = MAX_VOLUME : Gosub Send ; Set volume
  Return

FadeDownVolume:
  For arg = MAX_VOLUME To 0 Step - 1  
    cmd = MP3_SET_VOLUME : Gosub Send ; Set volume, 'arg' set by outer FOR-NEXT
    Pause 2000
  Next
  Return

; Communication with DFPlayer

Send:
  SetFreq BAUD_FREQ
  Pause 1000
  SerOut TX, BAUD, ( $7E, $FF, $06, cmd, $00, arg.msb, arg.lsb, $EF )
  ;gosub Check_Busy
  SetFreq MDEFAULT
  Return
  
WaitForTrackToEnd:
Do
pause Busy_Delay
ReadAdc LDR, ldrLevel
if ldrLevel <95 then exit
loop while Busy_Pin=0  

Return
SetVolumeToOff:
  cmd = MP3_SET_VOLUME : arg = 0 : Gosub Send ; Set volume to off (zero)
  Return
  
FadeUpVolume:
  For arg = 0 To MAX_VOLUME  
    cmd = MP3_SET_VOLUME : Gosub Send ; Set volume, 'arg' set by outer FOR-NEXT
    Pause 1000
  Next
  Return
An earlier version works fine on the same circuit board, so it is not a hardware problem.
The version below is working fine
Code:
; Define hardware

Symbol LDR                = C.7
Symbol TX                 = C.0
Symbol Busy_Pin           = PinB.5
Symbol LDR_LEVEL_AT_DAWN  = 105      ; LDR reads higher than this during the day
Symbol LDR_LEVEL_AT_DUSK  =  95      ; LDR reads less than this at night

Symbol BAUD_FREQ          = M8
Symbol BAUD               = T9600_8

Symbol MP3_PLAY          = $12     ; play track
Symbol MP3_REPEAT_PLAY    = $08      ; Repeat play a track
Symbol MP3_STOP           = $16      ; Stop track playing
Symbol MP3_SET_VOLUME     = $06      ; Set the volume

Symbol MAX_VOLUME         = $1E      ; Max volume level, $1E = 30

; Variables

Symbol cmd                = b0
Symbol arg                = w1 ; b3:b2
Symbol arg.lsb            = b2
Symbol arg.msb            = b3

Symbol ldrLevel           = b4
Symbol Busy_Delay = 2000  ; Change Busy delay value here
; Main program

PowerOnReset:
  High TX

  Do
    Gosub WaitForDawn
    Gosub SetVolumeToFull
    Gosub PlayFirstTrack
    Gosub WaitForTrackToEnd
    Gosub PlaySecondTrackWithRepeat
    Gosub WaitForDusk
    Gosub FadeDownVolume
    Gosub StopTrack
  Loop
; Day and night handling

WaitForDawn:
  Do
    Gosub SleepForSomeTime
    Gosub ReadTheLdrLevel
  Loop Until ldrLevel > LDR_LEVEL_AT_DAWN
  Return

WaitForDusk:
  Do
    Gosub SleepForSomeTime
    Gosub ReadTheLdrLevel
  Loop Until ldrLevel < LDR_LEVEL_AT_DUSK
  Return

SleepForSomeTime:
  Sleep 1 ; Doesn't really matter how long we sleep for at this stage
  Return

ReadTheLdrLevel:
  ReadAdc LDR, ldrLevel
  Return
  
PlayFirstTrack: ; Handle track playing
cmd = MP3_PLAY : arg = 0001 : Gosub Send ;
;gosub WaitForTrackToEnd
 Return
 
; WaitForTrackToEnd:
 ;gosub Check_Busy        ; ????????????

 ;Return
 
PlaySecondTrackWithRepeat:
  cmd = MP3_REPEAT_PLAY : arg = 0002 : Gosub Send ; Repeat track '/MP3/0002.mp3'
  Return

StopTrack:
  cmd = MP3_STOP : arg = 0 : Gosub Send ; Stop playing track
  Return

; Handle volume control

SetVolumeToFull:
  cmd = MP3_SET_VOLUME : arg = MAX_VOLUME : Gosub Send ; Set volume
  Return

FadeDownVolume:
  For arg = MAX_VOLUME To 0 Step - 1  
    cmd = MP3_SET_VOLUME : Gosub Send ; Set volume, 'arg' set by outer FOR-NEXT
    Pause 2000
  Next
  Return

; Communication with DFPlayer

Send:
  SetFreq BAUD_FREQ
  Pause 1000
  SerOut TX, BAUD, ( $7E, $FF, $06, cmd, $00, arg.msb, arg.lsb, $EF )
  ;gosub Check_Busy
  SetFreq MDEFAULT
  Return
  
WaitForTrackToEnd:
Do
pause Busy_Delay
ReadAdc LDR, ldrLevel
if ldrLevel <95 then exit
loop while Busy_Pin=0  

Return
 

hippy

Ex-Staff (retired)
I tired is code that I have put together from Hippy's last coding and it is not functioning
In what way is it not functioning ?

The change, from the version which works to what doesn't, appears to be in adding false dawn and false dusk detection so my guess is there is a bug in that code or you simply aren't testing it in a way which is having it see an actual dawn or dusk.

If you have the board connected to the PC by the AXE027 USB cable you can add SERTXD commands at the start of each routine called from the main loop so you can see what it is doing, for example -
Rich (BB code):
#Picaxe 20M2
#No_Data
#Terminal 4800
Rich (BB code):
MainLoop:
  Pause 2000 ; Wait for Terminal window to be displayed
  SerTxd( "MainLoop", CR, LF )
  Do
    ...
  Loop
Rich (BB code):
WaitForDawn:
  SerTxd( "WaitForDawn", CR, LF )
  ...
  Return
Then, when it runs, the PE6 Terminal should show what the code is doing-
Rich (BB code):
MainLoop
WaitForDawn
SetVolumeToOff
PlayFirstTrack
FadeUpVolume
WaitForTrackToEnd
SetVolumeToOff
PlaySecondTrackWithRepeat
FadeUpVolume
WaitForDusk
FadeDownVolume
StopTrack
WaitForDawn
etc
If it shows "MainLoop"then "WaitForDawn", and nothing more, then it's stuck in the "WaitForDawn" routine, not ever exiting that.
 

regpye

New Member
If you have the board connected to the PC by the AXE027 USB cable you can add SERTXD commands at the start of each routine called from the main loop so you can see what it is doing, for example -
Thanks for that Hippy, I will test it later this evening and see what happens, I can do what you have suggested to try. Thanks
 

regpye

New Member
If it shows "MainLoop"then "WaitForDawn", and nothing more, then it's stuck in the "WaitForDawn" routine, not ever exiting that.
I put the additions into the code and tested on the computer first using the C.7 rotary slider to set the values for dawn and dusk at different times.
It was stuck the WaitForDawn as you suspected.
There wasn't much point in testing the hardware as it would have given the same result.
So have I done something wrong, misinterpreted something somewhere?

MainLoop
WaitForDawn

slider first set at 19 and then 173, no change in the readout.

I remmed out ;Sleep SLEEP_UNITS_AT_NIGHT

and tried again at 173 and waited a little while and got this back
MainLoop
WaitForDawn
~[FF][06][06][00][00][00][EF]~[FF][06][12][00][00][01][EF]~[FF][06][06][00][00][00][EF]~[FF][06][06][00][00][01][EF]~[FF][06][06][00][00][02][EF]~[FF][06][06][00][00][03][EF]~[FF][06][06][00][00][04][EF]~[FF][06][06][00][00][05][EF]

Same test with the slider at a low level and it doesn't go past WaitForDawn which is correct

I tested again with a few more lines added and ran it with a daytime cycle to start with and then changed to a night time cycle.
It ended up waiting for dusk but it was already at dusk for sometime and just sitting there.

MainLoop
WaitForDawn
SetVolumeToOff

~[FF][06][06][00][00][00][EF]PlayFirstTrack
~[FF][06][12][00][00][01][EF]FadeUpVolume
~[FF][06][06][00][00][00][EF]~[FF][06][06][00][00][01][EF]~[FF][06][06][00][00][02][EF]~[FF][06][06][00][00][03][EF]~[FF][06][06][00][00][04][EF]~[FF][06][06][00][00][05][EF]~[FF][06][06][00][00][06][EF]~[FF][06][06][00][00][07][EF]~[FF][06][06][00][00][08][EF]~[FF][06][06][00][00] [EF]~[FF][06][06][00][00][EF]~[FF][06][06][00][00][0B][EF]~[FF][06][06][00][00][0C][EF]~[FF][06][06][00][00]
[EF]~[FF][06][06][00][00][0E][EF]~[FF][06][06][00][00][0F][EF]~[FF][06][06][00][00][10][EF]~[FF][06][06][00][00][11][EF]~[FF][06][06][00][00][12][EF]~[FF][06][06][00][00][13][EF]~[FF][06][06][00][00][14][EF]~[FF][06][06][00][00][15][EF]~[FF][06][06][00][00][16][EF]~[FF][06][06][00][00][17][EF]~[FF][06][06][00][00][18][EF]~[FF][06][06][00][00][19][EF]~[FF][06][06][00][00][1A][EF]~[FF][06][06][00][00][1B][EF]~[FF][06][06][00][00][1C][EF]~[FF][06][06][00][00][1D][EF]~[FF][06][06][00][00][1E][EF]WaitForTrackToEnd
SetVolumeToOff

~[FF][06][06][00][00][00][EF]PlaySecondTrackWithRepeat
~[FF][06][08][00][00][02][EF]FadeUpVolume
~[FF][06][06][00][00][00][EF]~[FF][06][06][00][00][01][EF]~[FF][06][06][00][00][02][EF]~[FF][06][06][00][00][03][EF]~[FF][06][06][00][00][04][EF]~[FF][06][06][00][00][05][EF]~[FF][06][06][00][00][06][EF]~[FF][06][06][00][00][07][EF]~[FF][06][06][00][00][08][EF]~[FF][06][06][00][00] [EF]~[FF][06][06][00][00][EF]~[FF][06][06][00][00][0B][EF]~[FF][06][06][00][00][0C][EF]~[FF][06][06][00][00]
I set it for dusk about here
[EF]~[FF][06][06][00][00][0E][EF]~[FF][06][06][00][00][0F][EF]~[FF][06][06][00][00][10][EF]~[FF][06][06][00][00][11][EF]~[FF][06][06][00][00][12][EF]~[FF][06][06][00][00][13][EF]~[FF][06][06][00][00][14][EF]~[FF][06][06][00][00][15][EF]~[FF][06][06][00][00][16][EF]~[FF][06][06][00][00][17][EF]~[FF][06][06][00][00][18][EF]~[FF][06][06][00][00][19][EF]~[FF][06][06][00][00][1A][EF]~[FF][06][06][00][00][1B][EF]~[FF][06][06][00][00][1C][EF]~[FF][06][06][00][00][1D][EF]~[FF][06][06][00][00][1E][EF]WaitForDusk
 
Last edited:

hippy

Ex-Staff (retired)
So have I done something wrong, misinterpreted something somewhere?
The output looks to be what I'd expect, the "~[FF][06][06][00][00][00][EF]" are the commands the 'send' routine is sending to the DFPlayer.

I would guess that it works with the SLEEP removed simply means you aren't leaving it long enough to detect a true dawn rather than a false dawn.

The stuff after"I set it for dusk about here " is the volume still fading up. Once it has reached maximum, '[1E]', it then enters the 'WaitForDusk' routine while still notionally playing track two.
 

regpye

New Member
The stuff after"I set it for dusk about here " is the volume still fading up. Once it has reached maximum, '[1E]', it then enters the 'WaitForDusk' routine while still notionally playing track two.
So I should give it another try and wait longer. I will put the sleep routine in again and test once or twice more.
 

regpye

New Member
Okay it is working fine, better than expected.
I tried using the hardware this morning and a lot more patience (that is all that was needed, patience)
The results in real time were perfect and the screen results are shown below

MainLoop
WaitForDawn waited about 3 minutes for this to clear
SetVolumeToOff
PlayFirstTrack
FadeUpVolume
WaitForTrackToEnd
SetVolumeToOff
PlaySecondTrackWithRepeat
FadeUpVolume
WaitForDusk waited about 3-4 minutes for this to finish
FadeDownVolume
StopTrack
WaitForDawn I switched off here as it would now repeat the whole process again.

Hippy, you are a great programmer and a very good teacher too.

I will put the completed code below for others to learn from and leave the extra lines in as well.
 
Last edited:

regpye

New Member
Completed and working code

Code:
; *******************************
;    Written by: HIPPY
;    Function:   Birds calling, start at dawn play first short 
;    track (12 minutes) then play second track that repeats until dusk, goes
;    to sleep mode to conserve battery     
;    Target PICAXE: 20M2   can be run on 08M2 by changing LDR, 
;    TX and BUSY_Pin
; *******************************
#Picaxe 20M2
#No_Data
#Terminal 4800
; Define hardware

Symbol LDR                = C.7
Symbol TX                 = C.0
Symbol Busy_Pin           = PinB.5
Symbol LDR_LEVEL_AT_DAWN  = 105      ; LDR reads higher than this during the day
Symbol LDR_LEVEL_AT_DUSK  =  95      ; LDR reads less than this at night

Symbol BAUD_FREQ          = M8
Symbol BAUD               = T9600_8

Symbol MP3_PLAY          = $12     ; play track
Symbol MP3_REPEAT_PLAY    = $08      ; Repeat play a track
Symbol MP3_STOP           = $16      ; Stop track playing
Symbol MP3_SET_VOLUME     = $06      ; Set the volume

Symbol MAX_VOLUME         = $1E      ; Max volume level, $1E = 30

; Variables

Symbol cmd                = b0
Symbol arg                = w1 ; b3:b2
Symbol arg.lsb            = b2
Symbol arg.msb            = b3

Symbol ldrLevel           = b4
Symbol Busy_Delay = 2000  ; Change Busy delay value here
; We only need to sleep for short periods during the day as
; the battery should be recharging. At night time we sleep
; for a longer period.
;
; Though each 'sleep' unit is about 2.3 seconds we will
; pretend it's a round 2 seconds. It might actually be one 
; to four seconds but it doesn't really matter if we are a 
; few minutes sooner or later in detecting dawn or dusk.

Symbol SLEEP_SECS_DURING_DAY   = 2 ; Multiples of 2 and 2 minimum
Symbol SLEEP_SECS_AT_NIGHT     = 8 ; Multiples of 2 and 2 minimum

Symbol SLEEP_UNITS_DURING_DAY  = SLEEP_SECS_DURING_DAY / 2
Symbol SLEEP_UNITS_AT_NIGHT    = SLEEP_SECS_AT_NIGHT   / 2

; If we get a dawn or dusk which lasts this long we consider
; it to be a fact. Any dusk or dawn which is shorter we can
; consider a 'false dawn' or 'false dusk' and ignore that.

Symbol DAWN_PERIOD_SECS        = 300 ; 300 secs = 5 minutes
Symbol DUSK_PERIOD_SECS        = 300 ; 300 secs = 5 minutes

; Keep track of how long we have detected a continuous dawn
; or dusk for.
  
Symbol secondsCounter          = w3 ; b7:b6

; Main program


PowerOnReset:

;MainLoop:
  Pause 2000 ; Wait for Terminal window to be displayed
  SerTxd( "MainLoop", CR, LF )
  High TX

  Do
    Gosub WaitForDawn
    ; Track 1 - Software fade-in, fade-out in track itself 
    Gosub SetVolumeToOff
    Gosub PlayFirstTrack
    Gosub FadeUpVolume
    Gosub WaitForTrackToEnd
    ; Track 2 - Software fade-in, repeat without fading, software fade-out at dusk
    Gosub SetVolumeToOff
    Gosub PlaySecondTrackWithRepeat
    Gosub FadeUpVolume
    Gosub WaitForDusk
    Gosub FadeDownVolume
    Gosub StopTrack
  Loop
; Day and night handling

WaitForDawn:
SerTxd( "WaitForDawn", CR, LF )
  secondsCounter = 0
  Do
    ; We are waiting for dawn so can presume we are running
    ; at night time
   Sleep SLEEP_UNITS_AT_NIGHT
    Gosub ReadTheLdrLevel
    If ldrLevel > LDR_LEVEL_AT_DAWN Then
      ; It is potentially dawn, so we count how long dawn seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_AT_NIGHT
    Else
      ; It is not dawn so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dawn, not a false dawn, then
    ; we return, otherwise keep going round the loop until it is
    ; dawn
  Loop Until secondsCounter >= DAWN_PERIOD_SECS
  Return

WaitForDusk:
SerTxd( "WaitForDusk", CR, LF )
  secondsCounter = 0
  Do
    ; We are waiting for dusk so can presume we are running
    ; during the day
    Sleep SLEEP_UNITS_DURING_DAY
    Gosub ReadTheLdrLevel
    If ldrLevel < LDR_LEVEL_AT_DUSK Then
      ; It is potentially dusk, so we count how long dusk seems
      ; to have lasted for
      secondsCounter = secondsCounter + SLEEP_SECS_DURING_DAY
    Else
      ; It is not dusk so we reset the counter
      secondsCounter = 0
    End IF
    ; If it appears to actually be dusk, not a false dusk, then
    ; we return, otherwise keep going round the loop until it is
    ; dusk
  Loop Until secondsCounter >= DUSK_PERIOD_SECS
  Return
  
SleepForSomeTime:
SerTxd( "SleepForSomeTime", CR, LF )
  Sleep 1 ; Doesn't really matter how long we sleep for at this stage
  Return

ReadTheLdrLevel:
  ReadAdc LDR, ldrLevel
  Return
  
PlayFirstTrack: ; Handle track playing
SerTxd( "PlayFirstTrack", CR, LF )
cmd = MP3_PLAY : arg = 0001 : Gosub Send ;
;gosub WaitForTrackToEnd
 Return
 

PlaySecondTrackWithRepeat:
SerTxd( "PlaySecondTrackWithRepeat", CR, LF )
  cmd = MP3_REPEAT_PLAY : arg = 0002 : Gosub Send ; Repeat track '/MP3/0002.mp3'
  Return

StopTrack:
SerTxd( "StopTrack", CR, LF )
  cmd = MP3_STOP : arg = 0 : Gosub Send ; Stop playing track
  Return

; Handle volume control

SetVolumeToFull:
SerTxd( "SetVolumeToFull", CR, LF )
  cmd = MP3_SET_VOLUME : arg = MAX_VOLUME : Gosub Send ; Set volume
  Return

FadeDownVolume:
SerTxd( "FadeDownVolume", CR, LF )
  For arg = MAX_VOLUME To 0 Step - 1  
    cmd = MP3_SET_VOLUME : Gosub Send ; Set volume, 'arg' set by outer FOR-NEXT
    Pause 2000
  Next
  Return

; Communication with DFPlayer

Send:

  SetFreq BAUD_FREQ
  Pause 1000
  SerOut TX, BAUD, ( $7E, $FF, $06, cmd, $00, arg.msb, arg.lsb, $EF )
  ;gosub Check_Busy
  SetFreq MDEFAULT
  Return
  
WaitForTrackToEnd:
SerTxd( "WaitForTrackToEnd", CR, LF )
Do
pause Busy_Delay
ReadAdc LDR, ldrLevel
if ldrLevel <95 then exit
loop while Busy_Pin=0  

Return
SetVolumeToOff:
SerTxd( "SetVolumeToOff", CR, LF )
  cmd = MP3_SET_VOLUME : arg = 0 : Gosub Send ; Set volume to off (zero)
  Return
  
FadeUpVolume:
SerTxd( "FadeUpVolume", CR, LF )
  For arg = 0 To MAX_VOLUME  
    cmd = MP3_SET_VOLUME : Gosub Send ; Set volume, 'arg' set by outer FOR-NEXT
    Pause 1000
  Next
  Return
 
Top