Using 'Max' and 'Min' together to limit variable, How?

elanman99

Senior Member
I have looked through the manual/s and have read the section on using maths with variables but so far have not found out how to limit the upper and lower value of (Pulsout, in this case) to restrict the range of servo travel.

Sorry if this is a really simple question that I should be able to work out from the manuals but I can use the Max and Min OK but dont know how to invoke both at the same time.


Ian
 

elanman99

Senior Member
I 'sort of' tried two lines, the syntax checker approved, but this bit of code did not work. (CW and ACW are my 'End Of Travel' points)

Ultimately I want the programme to alter the equation values so that the full ADC range is always used even though the servo might only need to cover a small arc of movement. Endpoints will be set by the user pressing button.

I will try your example now, thanks.

Ian


Code:
readadc10 C.1,POSN		' Gives 0-1023 counts

	POSN=POSN *2/15+80		' Convert ADC number to 80 to 216  (gives 400 to 1100 uS pulses)

	POSN=POSN max CWEOT		'
	
	POSN=POSN min ACWEOT		'

	pulsout pulses, POSN		' Send signal to servo
 

AllyCat

Senior Member
Hi Ian,

Often the quickest way to answer such questions is to invoke the Simulator in the Program Editor. It took only a minute to cobble together the following:
Code:
for b0 = 0 to 10
b1 = b0 min 2 max 8
sertxd(#b1," ")
next
That should not only answer your question, but further ones such as: Is b0 max 8 min 2 the same? And what about b0 max 2 min 8 or whether/when b1 could be replaced by b0?

Cheers, Alan.

PS: Your example code doesn't show the declarations (symbols) so we can't check why it may not be working correctly. POSN is declared as a Word variable isn't it?
 

elanman99

Senior Member
This is the first part of my programme. I put numeric values in for the EOTs for test purposes.

I use the simulator all the time but I dont really know how to get the best out of it. I look at the values of the memory locations but have not yet got my head round relating them to real life.

Ian


Code:
Symbol Pulses =  0			'
Symbol POSN   = W0			' Current servo position
Symbol Delay  = b2			'
Symbol CWEOT  = b3			' Clockwise End Of Travel, Set by user
Symbol ACWEOT = b4			' Anticlockwise End of Travel, Set by user

'Init:  B2 = 0

	Let delay = 20			' Adjust this value to get pulse repetion rate to 20mS

	Let CWEOT = 95
	
	Let ACWEOT = 190
 

AllyCat

Senior Member
Hi Ian,

There are times when using too many symbols can lead to confusion. Your code appears to be using a MIN of 190 and MAX of 95.

Note that you can expand the simulation panel with the >> at the bottom corner and can select to display either bytes or words.

Cheers, Alan.
 

elanman99

Senior Member
I'm still working on this project and have some more questions.

Unsurprisingly I get odd results from the routine that chooses two different option depending on the value of a pot on an analogue input pin.

Code:
Record:						; Store end (stop) positions for both ends of servo travel
	
	if ADCVAL >128 then WriteHighVal
	if ADCVAL <128 Then WriteLowVal	     
	Return
I tried using <127 and =>128 but that did not seem to work either (in the simulator). What is the best way to make a definite choice?

Another thing I cannot find in the dosumentation relates to the simulator. When I use the single step mode it 'appears' to skip over the first line of any routine it jumps to. I think it still executes it but the cursor does not highlight it. Is that normal?

Ian
 

Rick100

Senior Member
I'm still working on this project and have some more questions.

Unsurprisingly I get odd results from the routine that chooses two different option depending on the value of a pot on an analogue input pin.

Code:
Record:						; Store end (stop) positions for both ends of servo travel
	
	if ADCVAL >128 then WriteHighVal
	if ADCVAL <128 Then WriteLowVal	     
	Return
I tried using <127 and =>128 but that did not seem to work either (in the simulator). What is the best way to make a definite choice?

Another thing I cannot find in the dosumentation relates to the simulator. When I use the single step mode it 'appears' to skip over the first line of any routine it jumps to. I think it still executes it but the cursor does not highlight it. Is that normal?

Ian

You might want to upload your entire program . It appears your jumping outside your subroutine .
 

elanman99

Senior Member
Rick

This is where I am up to at the moment. Most of the remarks in the code are for my own benefit but might explain some of my off the wall logic.

I have read Manual 1, 2 and 3 and still cannot get my head round how some of the memory is addressed and labelled. The two panes in the simulator help and I have been trying to fathom what each value means by single stepping after changing the read and write addresses in the code.
In manual 2, the 'Write' example writes to b0 (presumably after having 'read' b1. Yet I can use lines like 'Write 3,variable' with no mention of 'b' numbers.
Is there a really good explanation that I can read?

Code:
; Focus Servo for underwater camera using 08M Picaxe
; Servo lead on		Output 0	(Pin 7) 
; Focus Pot wiper		Input  1	(Pin 6) 5k Pot between +5v and ground
; Centralise Switch	Input  4	(Pin 3) Pull up 'R' with switch to ground
; Save End Posn Switch	Input	 3	(Pin 4) Pull up 'R' with switch to ground
; Update/Save switch	Input	 2	(Pin 5) Pull up 'R' with switch to ground
; 400 to 1100uS PWM needs 80 to 216 to servo (Gives 8 turns of feedback pot)


Output 0						;Configure i/o pins of 08M, not sure if all are needed
Input  1
Input  2
Input  3
Input  4
;Setfreq m8						; Might try increasing pulsout resolution later 
Symbol ADCVAL	= b0				; ADC reading (0 to 255)
Symbol POSN		= b2				; Servo Position
Symbol Multi 	= b3				; Multiplier value for formula
Symbol Divi		= b4				; Divisor value for formula
Symbol Offset	= b5				; Offset value for formula
Symbol Span       = b6
			
Main:	
	pause 20					; Adjust this value to get pulse repetion rate to 20mS
	if Pin3 = 0 then Goto Record		; Write current position value to memory
	if Pin2 = 0 then Goto Update		; Write default equation values to memory
	if Pin4 = 0 then Goto Centralise	; Put servo mid travel and reset end stops to allow full travel
					
	Read 2,Multi				; Multiplier (might always be 100)
	Read 3,Divi					; Divisor so get correct output scaling
	Read 4,Offset				; Basically same value as one end stop
	Readadc 1,ADCVAL				; Gives 0-255
	POSN = ADCVAL *Multi/Divi+Offset	; Convert ADC number to 80 to 216 (full travel of my servo)
	Pulsout Output0,POSN			; Send signal to servo
	Goto Main
	
Centralise:						; Also 'resets' system so full travel available for users setup
	Pause 20					; Adjust this value to get pulse repetion rate to 20mS
	Pulsout Output0,148			; Force servo to mid position for user setup (148 gives 744uS)
	Write 2,100					; Default Value for Multiplier
	Write 3,187					; Default for Divisor
	Write 4,80					; Default for offset
	Goto main
	
Record:
	Readadc 1, ADCVAL				; I put this line in to 'refresh' value as seen in simulator 
	if ADCVAL <=128 Then WriteLowVal	; Store end (stop) positions for both ends of servo travel
	if ADCVAL  >128 then WriteHighVal	;  
	Return


Update:						; Takes the two stored values. Calculates correct value for
							; using in the equation and writes the new factors to memory
	Span = b9 - b7				; Difference between the two end stop numbers (ADC values)
	Divi = 255 / Span				; 
	Write b6,Divi				; Divisor				; 
	Write b8,b3					; Offset
	Goto Main


WriteLowVal:
	Write 6,ADCVAL				; I save both numbers here until I can decide which one is really 
	Write 5,POSN				; needed (by seeing in simulator whisch is the one I should use)
	Goto Main
	
WriteHighVal:
	Write 7,POSN				; I save both numbers here until I can decide which one is really
	Write 8,ADCVAL				; needed (by seeing in simulator whisch is the one I should use)
	Goto Main
 

Rick100

Senior Member
Under your main label you have a 'goto' statement that 'goto's a subroutine . Subroutines should be entered with a 'gosub' command . Subroutines should end with a 'return' command . In your subroutine 'record' you have a 'then WriteLowVal' which jumps to the 'WriteLowVal' label which then jumps back to 'main' with a 'goto' command . You will have to iron out these issues or you will have erratic behaviour . I don't know if you intended for record to be a subroutine . You can try replacing the return under the label 'Record' with a 'goto main' .

In the write command example the 'write b0,b1' means write the value held in 'b1' to the data address referred to in 'b0' . For example if 'b1' holds a value of 20 and 'b0' holds a value of 0 , then data address 0 will contain a value of 20 after the 'write b0,b1' .The command 'write 0,20' will do the same thing .The data address can be between 0 and 255 . The data address is part of the microcontroller flash memory and is totally different from the ram addresses like 'b0' and 'b1' .

Keep trying . Your closer than you think .

Good luck
Rick
 

elanman99

Senior Member
Rick

Thanks, particularly for your last, very encouraging! sentence.

Other than main, all the other sections were meant to be subroutines so they all now end with Returns (and I used Gosub). Looks much better in the simulator now and although I still have to improve/finish the Update routine all the rest works on the hardware.

Regarding the memory, I understand the difference between the different types of memory, what confuses me still is, writing to 'b1' being the same as writing to '1'.

In your example (write b0,b1), is the value then held by b0 a Variable? (say one that has been created by 'Symbol')

What I want to do is some maths on two stored values, save the result and then use it in my scaling formula. I can see the number in the data memory pane. do I just Read 'n' (ie without the 'b') but then Write it as 'b' 'n', or do I just use the variable name after the Write?

Ian
 

Rick100

Senior Member
Rick

Regarding the memory, I understand the difference between the different types of memory, what confuses me still is, writing to 'b1' being the same as writing to '1'.
Writing to 'b1' is only the same as writing to '1' if b1 holds a value of 1 . If b1 holds a value of 5 , then address 5 will be written to .

In your example (write b0,b1), is the value then held by b0 a Variable? (say one that has been created by 'Symbol')
b0 is a variable and can only hold a value between 0 and 255 . It can not hold another variable . It's like a box that you can put a value in . It can't hold another box . In this case the value is an address for the write command .

What I want to do is some maths on two stored values, save the result and then use it in my scaling formula. I can see the number in the data memory pane. do I just Read 'n' (ie without the 'b') but then Write it as 'b' 'n', or do I just use the variable name after the Write?
To read a value from data memory into a variable use 'read address, variable' where address is a number between 0 and 255 and variable is any byte variable like b0 . Ex: 'read 10,b0' reads whats in address 10 into b0 .

I would just define the addresses for the values at the top of the program as constants .I don't see any reason the addresses should be variables . I have included a sample program to run in the simulator . It uses constant address definitions and subroutines . When you load the program into the picaxe editor do a syntax check . After that look to the left of the screen to see the variables and constants that have been defined . Variables that have not been given symbol names won't show up there . You can then step through the program watching the values change in the simulation panes .

Code:
'Run in simulator for demonstration
'after syntax check look at left pane to see variables and constants


'Constants used by subroutines
'constant values are set when you write the program and can't be changed by the running program
symbol DEF_CAL_VAL1 = 50		'default calibration value1
symbol DEF_CAL_ADDRESS1 = 10	'address to store default calibration value1

symbol DEF_CAL_VAL2 = 75		'default calibration value2
symbol DEF_CAL_ADDRESS2 = 11	'address to store default calibration value2


symbol someVar = b12 	'will not be used in program


'demonstrate using variables for write command
b1 = 20
for b0 = 0 to 7
	write b0,b1
	b1 = b1 + 1	' increment for easier observation
next


'demonstrate using variables for read command
for b0 = 0 to 7
	read b0,b1 ; read value at b0 into b1 / watch b0 , b1 and memory pane in simulator
next

'demonstrate using different variables for write command
b2 = 30
for b3 = 0 to 7
	write b3,b2
	b2 = b2 + 1	' increment for easier observation
next

'demonstrate using different variables for read command
for b3 = 0 to 7
	read b3,b2 ; read value at b3 into b2 / watch b2 , b3 and memory pane in simulator
next


'demonstrate using subroutines to save and retrieve calibration values


gosub storeDefaults	'resets the calibration to constants defined when writing program


gosub getCalVals	'put calibration values from data memory in variables b0 and b1 so program can modify them


b0 = 125	'calibration values to store
b1 = 32	'
gosub storeCalVals 'store values in b0 and b1 into addresses 10 and 11


b0 = 0	'clear variables for easier observation
b1 = 0
gosub getCalVals	'put calibration values from data memory in variables b0 and b1 so program can modify them


end

storeDefaults:	'reset calibration values to constants
	write DEF_CAL_ADDRESS1,DEF_CAL_VAL1	'same as write 10,50
	write DEF_CAL_ADDRESS2,DEF_CAL_VAL2	'same as write 11,75
return


storeCalVals:
	write DEF_CAL_ADDRESS1,b0	'write value held in b0 to address 10
	write DEF_CAL_ADDRESS2,b1	'write value held in b1 to address 11
return

getCalVals:
	read DEF_CAL_ADDRESS1,b0	'read stored calibration values into variables
	read DEF_CAL_ADDRESS2,b1	'so program can adjust them
return

Hope this helps .

Good luck,
Rick
 

elanman99

Senior Member
Rick

Thanks for all your help. I copied and saved your code and have run it a couple of times in the simulator. I can see, or more importantly, can now understand what is happening.

I will step through it slowly and spend some more time studying it later this evening.

Ian
 
Top