Coding Challenge for 3 mode game

rxhul

Active member
Dear all,

I am having some difficulties with writing a program which has 4 push to make switches and a pot as the input and 3 LEDs + buzzer as the output.

I am attaching a picture of my PCB below although I appreciate this may not be helpful so I will also attempt to explain the function.

It is a bit complex so if it needs explaining again I am of course happy to do so and apologise if it is confusing.

23695

1. So, the user turns the device on
2. The press PTM (push to make) number 1 to activate mode 1.
3. In mode 1, the 3 LEDs come on at a "slow" fixed intervals.
4. Each LED has a corresponding PTM (out of the three remaining ones).
5. When the LED comes on, the corresponding PTM must be hit.
6. When the PTM is hit, (goes high), then the LED goes off and the buzzer sounds. This happens every time in later modes too.
7. Then another LED comes at the same "slow" fixed intervals and the process repeats
8. The user then uses the potentiometer to shorten the rate at which the LEDs come on - i.e they come on faster.
9. They can then press PTM number 1 again to move to mode 2
10. In this mode the LEDs come on randomly/random intervals but otherwise this is the same as mode 1.
11. The user presses PTM 1 to mode to mode 3
12. In this mode, the PIC measures 20 seconds.
13. The user uses the pot to set a setting - EASY MED or HARD (for example)
14. Each setting has a corresponding number eg. 10 hits, 20 hits, 30 hits
15. The user have to try and hit the PTMs as many times as they can in 20 seconds (but cannot hit the same PTM every time).
16. If the user hits the required number in the time, the buzzer beeps a couple of times.
17. Pressing PTM 1 again goes back to mode 1.

I wanted to write a code for the above function in Picaxe editor for a Picaxe 14M2

Many many thanks in advance to everyone,

Best wishes,
 
Last edited:

hippy

Technical Support
Staff member
Sounds like a fun game. The best way to approach any project is incrementally; get something simple working first then tweak that to do what you actually want, make the timing dependent on the pot position, add more modes, etc.

Don't forget to save each version so you can easily start again from where you were, with something known to work, if you mess something up.

I would start with a simple 'press the main button to start', some time later a LED comes on, hit the corresponding button and that goes off, some other LED comes on, repeat ad infinitum.

Untested, and you will have to adjust the SYMBOL definitions -
Code:
#Picaxe 14M2
#No_Data

Symbol BUTTON_MODE   = pinC.0
Symbol BUTTON_1      = pinC.1
Symbol BUTTON_2      = pinC.2
Symbol BUTTON_3      = pinC.3

Symbol PUSHED        = 1 ; Active high when a button is pushed

Symbol LED1          = B.1
Symbol LED2          = B.2
Symbol LED3          = B.3

Symbol SOME_TIME     = 4000 ; 4 seconds

Symbol randomNumber  = w1 ; b3:b2
Symbol ledNumber     = b4
Symbol lastLedNumber = b5

WaitForMainButtonPush:
  Gosub AllLedsOff
  Do
    Random randomNumber
  Loop Until BUTTON_MODE = PUSHED

Game1:
  Do
    Pause SOME_TIME
    Gosub ChooseLedToLight
    Gosub LightTheLed 
    Gosub WaitUntilButtonPushed
    Gosub AllLedsOff
  Loop

AllLedsOff:
  Low LED1
  Low LED2
  Low LED3
  Return

ChooseLedToLight:
  lastledNumber = ledNumber
  Do
    Random randomNumber
    ledNumber = randomNumber // 3 + 1 ; 1 to 3
  Loop Until ledNUmber <> lastLedNumber
  Return

LightTheLed:
  Select Case ledNumber
    Case 1 : High LED1
    Case 2 : High LED2
    Case 3 : High LED3
  End Select
  Return

WaitUntilButtonPushed:
  Select Case ledNumber
    Case 1 : Do : Loop Until BUTTON_1 = PUSHED
    Case 2 : Do : Loop Until BUTTON_2 = PUSHED
    Case 3 : Do : Loop Until BUTTON_3 = PUSHED
  End Select
  Return
 

rxhul

Active member
Many thanks hippy, so as far as I see it, the above code works for stage 1 in what you call incremental coding. i.e for now this works for Game 1 and I still have to do Game 2 and 3...?

I will programme this onto my circuit tomorrow and try to make additions like you suggest, making sure to save.

Hopefully you won't mind me coming back to this thread if I run into trouble again!

Many thanks
 
Last edited:

rxhul

Active member
Also, sorry to bother you - what do you mean when you say I will have to adjust some of the symbol definitions?
 

hippy

Technical Support
Staff member
what do you mean when you say I will have to adjust some of the symbol definitions?
Basically you need to ensure the BUTTON definitions refer to the pins you have your buttons connected to and the LED definitions to the pins you have your LEDs connected to.
 

rxhul

Active member
Thanks hippy for the help earlier this month.

Due to COVID-19, my plans were disrupted, but now I can say that the initial program works as I want.

What is the next stage incrementally.

Also, I would like to change one function:

mode 4:
HANDHELD mode - only LED 2 can come, and it just comes on randomly. When the corresponding PTM is hit, the led goes off and the buzzer sounds.

Many thanks :)
 

hippy

Technical Support
Staff member
It might be best to post your code so far so whatever is suggested can be best integrated with that but in general you probably want something like -
Code:
Game4:
  Do
    Gosub AllLedsOff
    Gosub WaitForSomeRandomTime
    ledNumber = 2
    Gosub LightTheLed 
    Gosub WaitUntilButtonPushed
    Gosub SoundBuzzer
  Loop
 

rxhul

Active member
Symbol BUTTON_MODE = pinC.0
Symbol BUTTON_1 = pinC.1
Symbol BUTTON_2 = pinC.2
Symbol BUTTON_3 = pinC.3

Symbol PUSHED = 1 ; Active high when a button is pushed

Symbol LED1 = B.1
Symbol LED2 = B.2
Symbol LED3 = B.3

Symbol SOME_TIME = 4000 ; 4 seconds

Symbol randomNumber = w1 ; b3:b2
Symbol ledNumber = b4
Symbol lastLedNumber = b5

WaitForMainButtonPush:
Gosub AllLedsOff
Do
Random randomNumber
Loop Until BUTTON_MODE = PUSHED

Game1:
Do
Pause SOME_TIME
Gosub ChooseLedToLight
Gosub LightTheLed
Gosub WaitUntilButtonPushed
Gosub AllLedsOff
Loop

AllLedsOff:
Low LED1
Low LED2
Low LED3
Return

ChooseLedToLight:
lastledNumber = ledNumber
Do
Random randomNumber
ledNumber = randomNumber // 3 + 1 ; 1 to 3
Loop Until ledNUmber <> lastLedNumber
Return

LightTheLed:
Select Case ledNumber
Case 1 : High LED1
Case 2 : High LED2
Case 3 : High LED3
End Select
Return

WaitUntilButtonPushed:
Select Case ledNumber
Case 1 : Do : Loop Until BUTTON_1 = PUSHED
Case 2 : Do : Loop Until BUTTON_2 = PUSHED
Case 3 : Do : Loop Until BUTTON_3 = PUSHED
End Select
Return

This is my code up until now (The one you suggested - it worked a treat :) )
 

rxhul

Active member
I still need to:

incorporate my POT (see first post) and my buzzer into this code
and I need to do 8-17

8. The user then uses the potentiometer to shorten the rate at which the LEDs come on - i.e they come on faster.
9. They can then press PTM number 1 again to move to mode 2
10. In this mode the LEDs come on randomly/random intervals but otherwise this is the same as mode 1.
11. The user presses PTM 1 to mode to mode 3
12. In this mode, the PIC measures 20 seconds.
13. The user uses the pot to set a setting - EASY MED or HARD (for example)
14. Each setting has a corresponding number eg. 10 hits, 20 hits, 30 hits
15. The user have to try and hit the PTMs as many times as they can in 20 seconds (but cannot hit the same PTM every time).
16. If the user hits the required number in the time, the buzzer beeps a couple of times.
17. Pressing PTM 1 again goes back to mode 1.
 

rxhul

Active member
Hi hippy,

just a quick question about my earlier coding challenge which you were helping out in

firstly, how do I program for an adc value i.e. a potentiometerm so that the higher the value the the faster the leds come on I.e. symbol SOME TIME decreases?
and, how do I incorporate my buzzer so that it sounds when the button is hit.

secondly, how would I program for RANDOM intervals rather than a fixed interval for which the LEDS come on?

finally, how would I program my game mode 3 for which the pic times 20 seconds and it is a race against time?
many thanks,

hope you’re well:)

Yesterday at 7:39 PM
For ease of integration, this is my code so far:

Code:
Symbol BUTTON_MODE = pinC.4
Symbol BUTTON_1 = pinC.3
Symbol BUTTON_2 = pinC.1
Symbol BUTTON_3 = pinC.2
Symbol POT_ = pinC.0
Symbol PUSHED = 1
Symbol LED1 = B.4
Symbol LED2 = B.1
Symbol LED3 = B.3
Symbol Buzzer = B.5
Symbol SOME_TIME = 4000
Symbol randomNumber = w1;b3:b2
Symbol ledNumber = b4
Symbol lastLedNumber = b5
WaitForMainButtonPush:
Gosub AllLedsOff
Do
Random randomNumber
Loop Until BUTTON_MODE = PUSHED
Game1:
Do
Pause SOME_TIME
Gosub ChooseLedToLight
Gosub LightTheLed
Gosub WaitUntilButtonPushed
Gosub AllLedsOff
Loop
AllLedsOff:
Low LED1
Low LED2
Low LED3
Return
ChooseLedToLight:
lastledNumber=ledNumber
Do
Random randomNumber
ledNumber = randomNumber // 3+1
Loop Until ledNumber <> lastLedNumber
Return
LightTheLed:
Select Case ledNumber
Case 1: High LED1
Case 2: High LED2
Case 3: High LED3
End Select
Return
WaitUntilButtonPushed:
Select Case ledNumber
Case 1: Do: Loop Until BUTTON_1 = PUSHED
Case 2: Do: Loop Until BUTTON_2 = PUSHED
Case 3: Do: Loop Until BUTTON_3 = PUSHED
End Select
Return
For the random time - would I use the same code but increase the numbers i.e.
Symbol RandomTime = w2;b6;b7
RandomTime = random // 4000+1

??
 
Last edited:

lbenson

Senior Member
Not an answer to your question, but if your code has indentation (as it should for readability), please post it between the forum tags, "[ code]" and "[ /code]" (without the spaces). You can edit your post to do this.
 

lbenson

Senior Member
There's still a space in the closing tag: "[ /code]".

Does your code have indentation? If so, you may need to copy it in again, within the forum tags, "[ code]" and "[ /code]" (without the spaces).
 

hippy

Technical Support
Staff member
how do I program for an adc value i.e. a potentiometer so that the higher the value the the faster the leds come on I.e. symbol SOME TIME decreases?
First thing is to define where the pot is connected to (POT_ADC) and define what the minimum and maximum period in milliseconds between lighting LED's will be (TIME_MIN and TIME_MAX).

Because you want the time to reduce with higher amounts of pot you would need to initially invert that so something like, untested ...
Code:
Symbol POT_ADC       = ?.?

Symbol TIME_MIN      = 150
Symbol TIME_MAX      = 5000

Symbol pauseTime     = w3 ; b7:b6

WaitForTimeSetByPot:
  ReadAdc10 POT_ADC, w0
  w0 = 1023 - w0
  pauseTime = TIME_MAX - TIME_MIN ** w0 * 64
  pauseTime = TIME_MAX - TIME_MIN *  w0 / 1024 + pauseTime + TIME_MIN
  Pause pauseTime
  Return
Then replace "Pause SOME_TIME" with "Gosub WaitForTimeSetByPot". And you can then delete the "Symbol SOME_TIME" definition.

how do I incorporate my buzzer so that it sounds when the button is hit.
Code:
Symbol PIEZO_OUT     = ?.?
Symbol PIEZO_NOTE    = 50
Symbol PIEZO_LENGTH  = 30

SoundBuzzer:
  Sound PIZEO_OUT, ( PIEZO_NOTE, PIEZO_LENGTH ) 
  Return
how would I program for RANDOM intervals rather than a fixed interval for which the LEDS come on?
Code:
Symbol RANDOM_TIME_MIN = 150
Symbol RANDOM_TIME_MAX = 5000

Symbol pauseTime       = w3 ; b7:b6

WaitForSomeRandomTime
  Random randomNumber
  pauseTime = RANDOM_TIME_MAX - RANDOM_TIME_MIN ** randomNumber + RANDOM_TIME_MIN
  Pause pauseTime
  Return
finally, how would I program my game mode 3 for which the pic times 20 seconds and it is a race against time?
That's a bit more complicated. I'll have to have a think on that.

PS: Fixed the erroneous space in [ /code] issue.
 

rxhul

Active member
Thanks hippy - why is the adc value for the POT 1023/1024?
If I am using 8 bit, won't the number be 255?
 

hippy

Technical Support
Staff member
why is the adc value for the POT 1023/1024?
If I am using 8 bit, won't the number be 255?
Correct, but might as well use 10-bit as it's available just by using READADC10 rather than READADC.

As to 1023 and/or 1024 - The pot value read will be 0 to 1023 but, when it comes to maths, it's much easier to divide by 1024, as that can be done purely by bit-shifting, though the bit shifting here is done by multiplying and dividing by numbers which are a power of 2.

The discrepancy in using 1024 rather than the correct 1023 is usually insignificant and fairly irrelevant for this application. No one will notice if the LED lights a few milliseconds earlier or later than how the pot is set.
 

AllyCat

Senior Member
Hi,
The discrepancy in using 1024 rather than the correct 1023
Actually, I think 1024 is the correct value. The "ADC Transfer Function" described in the Microchip data sheet (e.g. Figure 16-5 for M2s) shows 1025 levels where the 1025th is the Reference Voltage. But that level is not reported because it is an "overflow" into the 11th bit. Even more strangely, the ADC appears to include rounding, so the first step up from zero (the "Zero-Scale transition") occurs at 0.5 of the LS Bit. Therefore, the "Full-Scale Transition" (clearly shown in the diagram) is 1.5 LSBs below the Reference Voltage.

Cheers, Alan.
 

hippy

Technical Support
Staff member
I don't think any mere mortal has ever got entirely to grips with the ADC transfer function and reversing it and I am not convinced it's even possible in practice.

The main problem is that it's a non-reversible function. A particular ADC reading maps back to a range of input voltages, and it's not consistent across the full range. That means there is no simple division which accurately reverses the function.

And it's often more about meeting user's expectations than delivering an accurate answer, because the accurate answer feels wrong. With 0V and 5V in they expect to see that, not 0.25V and 4.5V for example.

The definitive ADC reference for the PIC16C7X range appears to be here -

 
Top