Merry Mix

#1
Hi Fellers. My project is a Merry Mix assembled from Meccano. The object was to simulate a fair ground Merry Mix, such that each ride was accompanied by a different tune. The processor is an 08M2 with leg 4 connected to a LED, motor drive via a BD139 to Leg 6, and a speaker connected via a cap and resistor to Leg 5.
The model works fine with the code, such that each time a 'ride' starts, the next tune in sequence plays:
start:
b0=b0+1
if b0=10 then call reset_b0
high 4 ; Led lights
wait 5
high 1 ;motor and music start
if b0=1 then call tune1
if b0=2 then call tune2
;etc through to tune 9
low 1 ;music stops, motor stops and spools down
low 4 ; LED extinguishes
wait 7
goto start

reset_b0:
b0=1
return

tune1: ;(RTTTL)
tune
0,6,($aa etc.....), and through to tune9
Return

My next attempt was/is to attempt to select and play a tune randomly. I used the code as above more or less, modified as follows:
Start:
high 4
wait 5
high 1
random w0 ;re-seed each cycle
if b0>=0 and b0<=28 then call tune 1
if b0>=28 and b0<=56 then call tune2
etc through to tune9 and <=255 - I used b0 as the LSB of w0.

low 1
low 4
wait 7
goto start

Then the 9 RTTTl tunes as abbreviated above.

This worked fine using the simulator function, and tunes played randomly. b0 changed each iteration, and the appropriate tune played. However, when I applied the program to the processor, I found that the tune always starts at tune1, and repeatedly plays tune1 each ride sequence -

I suspected a hardware glitch, so commented out the motor and LED functions, then increased the cap across the 08M2, but to no effect. I also tried various pause's between each 'if' statement. Nothing seemed to work.

It seems that the processor always wants to start at tune1, irrespectibe of the value of b0, and continue at tune1, even though b0 changes each cycle as displayed by the simulator, and even though the simulator does exactly what I want/expect. I've also tried a different 08M2 in case I'd done something naughty.

I think I'm stumped. Can anyone see a problem in what I've done or suggest a solution?

Ben Baker
 

Aries

New Member
#2
I suggest you put in some sertxd statements to show the flow through your code and the value of b0 at each step - e.g.
Code:
Start:
sertxd(13,10,"Starting")
high 4
wait 5
high 1
sertxd(13,10,"w0=",#w0)
random w0     ;re-seed each cycle
sertxd(" -> ",#w0," = ",#b0," ",#b1)
sertxd(13,10,"Pre tune 1 ",#b0)
if b0>=0 and b0<=28 then call tune 1
sertxd(13,10,"Pre tune 2 ",#b0)
if b0>=28 and b0<=56 then call tune2
sertxd(13,10,"Pre tune 3 ",#b0)
etc through to tune9 and <=255   -    I used b0 as the LSB of w0.
sertxd(13,10,"Post tune 9 ",#b0)
low 1
low 4
wait 7
sertxd(13,10,"End of code")
goto start

tune1:   ;(RTTTL)
sertxd(" tune 1")
tune
0,6,($aa etc.....),   and through to tune9
Return
and see what happens
 

hippy

Technical Support
Staff member
#3
It seems that the processor always wants to start at tune1, irrespectibe of the value of b0, and continue at tune1
If you mean, whenever the PICAXE is powered-up it starts with the first tune, that would be correct. Your random number in w0 will always be zeroed when the PICAXE powers up.

The easiest way to have it start with a different value is to 'seed' the starting value and change that seed so it has a differnt one next time. The easiest way to do that is to use the internal data eeprom. At the very start of your code, before your 'start:' label -
Code:
Read 0, b0
Random w0
Write 0, b0
You can also simplify your tune selection using -
Code:
Random w0
b2 = b0 / 26
On b2 Goto Tune1, Tune2, Tune3 ... Tunne8, Tune9
 
#4
I suggest you put in some sertxd statements to show the flow through your code and the value of b0 at each step - e.g.
Code:
Start:
sertxd(13,10,"Starting")
high 4
wait 5
high 1
sertxd(13,10,"w0=",#w0)
random w0     ;re-seed each cycle
sertxd(" -> ",#w0," = ",#b0," ",#b1)
sertxd(13,10,"Pre tune 1 ",#b0)
if b0>=0 and b0<=28 then call tune 1
sertxd(13,10,"Pre tune 2 ",#b0)
if b0>=28 and b0<=56 then call tune2
sertxd(13,10,"Pre tune 3 ",#b0)
etc through to tune9 and <=255   -    I used b0 as the LSB of w0.
sertxd(13,10,"Post tune 9 ",#b0)
low 1
low 4
wait 7
sertxd(13,10,"End of code")
goto start

tune1:   ;(RTTTL)
sertxd(" tune 1")
tune
0,6,($aa etc.....),   and through to tune9
Return
and see what happens


To Aries and Hippy. Thankyou guys. Haven't solved the problem yet, but you've both given me leads. I'll persevere with your suggestions.

Ben Baker
 
#5
With your code as is, w0 will start at zero. "RANDOM" generates a sequence of pseudo-random numbers (you can find references to how it works in other threads), but as a rough guide, it uses the formula w0 = w0 * 2 + X where X is 0 or 1 depending on certain bits in w0. It will generate all numbers in the range 1-65535 before repeating. However, it will start (0) 2 5 11 23 47 94 189 378, and so your first 4 values for b0 will all be less than 28, hence the first tune will repeat 4 times. The best thing to do is to start with a largeish value for w0 and go from there (saving the value in eeprom as Hippy suggests).
 
Last edited:

hippy

Technical Support
Staff member
#6
A good point about 'random' not always being as random as one would like. One trick is to not use the values as they are but use some more convoluted means of getting a number to use. This can mess-up random distribution but will often actually feel more random, for example -
Rich (BB code):
Random w0
b2 = w0 / 17 // 9 ; Gives a 0 to 8 value, Tune1 to Tune9
On b2 Goto Tune1, Tune2, Tune3 ... Tune8, Tune9
Sometimes one has to play with the divisor ( 17 here ) to get it feeling right. I tend to find prime numbers work best.
 
#7
A good point about 'random' not always being as random as one would like. One trick is to not use the values as they are but use some more convoluted means of getting a number to use. This can mess-up random distribution but will often actually feel more random, for example -
Rich (BB code):
Random w0
b2 = w0 / 17 // 9 ; Gives a 0 to 8 value, Tune1 to Tune9
On b2 Goto Tune1, Tune2, Tune3 ... Tune8, Tune9
Sometimes one has to play with the divisor ( 17 here ) to get it feeling right. I tend to find prime numbers work best.
I have used a variant of hippy's code above to good effect.
 
#9
To Aries, Hippy & Inglewoodpete. Thanks for your help, guys. Haven't got the thing working exactly as I wanted it, but using the internal EEPROM was a great idea. Never used it before (or understood it!), but at least I can get the tunes to start with the last one played at power-up, and then advance one tune at each iteration. There's so much I don't know. Guess I'll still keep trying with random.

Ben Baker
 
#10
I'm still intrigued to try to understand why you are - if I understand correctly - not getting a random effect when you use RANDOM. Did you put the sertxd's in as I suggested? If so, what are you seeing in the output on the terminal? There should be enough there to deduce what is going on.
 
#11
Aries & Hippy With your efforts, I've overcome the problem, but without using random. The Merry Mix now does pretty much as I wanted it to - a new tune at every power-on - which was the original reason for trying to use random. Don't care if I'm limited to 9 tunes repeating - I'll just add some more tunes!
This is the code I used:
Code:
start:
wait 5
high 1
read 0,b1
b1=b1+1
if b1=10 then call reset_b1
write 0,b1    ;this solved the 'next tune' problem
If b1=1 then call tune1
'etc through tune 9'
low 1
low 4
wait 7

goto start
reset b1:
b1=1
return

'then the 9 RTTTL tunes'
(My wife got pretty crabby over hearing the Star Wars Theme [tune1] over and over, so I had to do something!)

So whilst I haven't solved the use of random yet, that can wait 'til another day. Hopefully, it won't beat me. In the meantime, I've now learned a bit about the EEPROM facility and the value of the sertxd function as an analysis tool. Thanks guys. Maybe someone else reading this may benefit from your efforts.

Ben Baker, Tasmania (the island just south of Australia, in case your schoolboy geography has failed you - fortunately we're not in NZ where that madman [an Australian, I'm ashamed to say] just created so much grief).
 
Top