Request for program check

Hey guys,

I've finished writing this annoyingly long program for the master chip in a serial master-slave system. Unfortunately everyone I know who is also a programmer has no experience with the PICAXE system. My simulations seem to work just fine, but would some kind soul here be willing to check over the code?

Cheers guys!

Code:
'This is a program to receive inputs from a push-button matrix, and send commands to satellite PICAXE chips over a wired serial bus.
'
'Serial bus has two connection: One for communication to satellite chips, and one for replies from those chips. They only respond when spoken to.
'
'Buttons connected in matrix, with 11 rows & 11 columns giving 232 buttons - theoretical maximum for 8-bit operation due to addressing system used: 11 x 22 = 242. If more buttons needed, program would need updating to use words instead of individual bytes, giving a theoretical maximum of over 30,000 buttons.
'
'Chip used is a PICAXE 28X2
'
'I/O:
'	1x Serial in		C.0
'	1x Serial out		C.1
'	11x Matrix outputs	B.0-7, C.5-7
'	11x Matrix Inputs	A.0-7, C.2-4
'
'Standard serial formats:
'Serial Out:					For communication with satellite chips
'	serout C.1, N9600_16, (*address*, *command*, *command*)
'Serial In:
'	Serin C.0, N9600_16, (*address from*, *data*)	*address from* used for readiness checking
'
'Standard Serout commands:
'	(*address*, 255, 1)	Requesting chip to confirm readiness to receive data. Also used to indicate main chip ready to receive data.
'
'Standard chip responses:
'	(*address from*, %00000001)	Bit 0 = 1: no data to transmit
'	(*address from*, %*******0) 	Bit 0 = 0: data to transmit, data contained in bits 1-7. Will be implemented into program if ever needed, but groundwork implemented.
'					Both of the above are also confirmations of readiness to receive data.

'--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

'								MATRIX CONTROL

init:
	setfreq m16			'Set frequency to 16MHz
	let dirsb = 255			'B.0-7 matrix outputs
	let dirsa = 0			'A.0-7 matrix inputs
	let dirsc = %11100010		'C.0 serin, C.1 serout, C.2-4 matrix inputs, C.5-7 matrix outputs
	let pinsb = 0
	let pinsa = 0
	let pinsc = 0
	let b0 = 0			'Matrix outputs
	let b1 = 0			'Matrix inputs
	let b2 = 0			'Matrix result
	let b3 = 0			'Serout address byte
	let b4 = 0			'Serout data byte 1
	let b5 = 0			'Serout data byte 2
	let b6 = 0			'serin address byte
	let b7 = 0			'serin data byte

main:
	b1 = 0
	b2 = 0
	b3 = 0
	b4 = 0
	b5 = 0
	let pinsB = %10000000				'Chip switches on outputs one at a time and scans inputs after each change
	b0 = 1						'Outputs assigned addresses 1-11, inputs addresses 12-22
	gosub check
	let pinsB = %01000000
	b0 = 2
	gosub check
	let pinsB = %00100000
	b0 = 3
	gosub check
	let pinsB = %00010000
	b0 = 4
	gosub check
	let pinsB = %00001000
	b0 = 5
	gosub check
	let pinsB = %00000100
	b0 = 6
	gosub check
	let pinsB = %00000010
	b0 = 7
	gosub check
	let pinsB = %00000001
	b0 = 8
	gosub check
	let pinsb = 0
	high c.5
	b0 = 9
	gosub check
	low c.5
	high c.6
	b0 = 10
	gosub check
	low c.6
	high c.7
	b0 = 11
	gosub check
	if b1 > 0 then multiply				'If a button press detected, ie. b1 contains a value, then continue to carry out command
	goto main

multiply:
	b2 = b0*b1					'Multiply the addresses of the output & input together to give a unique ID of button pressed
	b2 = b2-10					'Take 10 away to make smallest possible address 1.
	if b2 = 0 then main
actuate:
	if pinsA = 1 or pinC.2 = 1 or pinC.3 = 1 or pinC.4 = 1 then actuate

	on b2 goto p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232

	goto main					'Goto script for button pressed

transmit:						'Transmit sub-procedure, to be called up by scripts.
	serout C.1, N9600_16, (b3, 255, 1)		'Request readiness confirmation from satellite chip
	serin [200, transmit], c.0, N9600_16, b6, b7	'Await response from satellite chip, store response in variables b6 & b7
	if b6 != b3 then transmit			'Ensure responding chip has correct address
	if b7 bit0 = 0 then readser			'If b7 bit 0 = 0, then chip has data to transmit.
transmit2:
	b6 = 0						'Reset serin variables.
	b7 = 0
	pause 5
	serout c.1, N9600_1, (b3, b4, b5)		'Transmit data to satellite chip. Data preset in script.
	serin [200, transmit], c.0, N9600_16, b6, b7	'Await receipt confirmation for 50ms, else attempt transfer again
	if b6 != b3 then transmit			'Confirm address and response transmitted by satellite chip correct, else attempt transfer again
	if b7 != 1 then transmit
	goto main

readser:
	goto transmit					'To be implemented if needed
	


end

'------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

									'SUB PROCEDURES

check:
	if pina.0 = 1 then let b1 = 12		
	endif
	if pina.1 = 1 then let b1 = 13
	endif
	if pina.2 = 1 then let b1 = 14
	endif
	if pina.3 = 1 then let b1 = 15
	endif
	if pina.4 = 1 then let b1 = 16
	endif
	if pina.5 = 1 then let b1 = 17
	endif
	if pina.6 = 1 then let b1 = 18
	endif
	if pina.7 = 1 then let b1 = 19
	endif
	if pinc.2 = 1 then let b1 = 20
	endif
	if pinc.3 = 1 then let b1 = 21
	endif
	if pinc.4 = 1 then let b1 = 22
	endif
	return

goto main

end

'------------------------------------------------------------------------------------------------------------------------------------------------------------------------

'									SCRIPTS

p1:
	goto main			'Scripts can be written here as needed

p2:
	goto main

p3:
	goto main

p4:
	goto main

p5:
	goto main

p6:
	goto main

p7:
	goto main

p8:
	goto main

p9:
	goto main

p10:
	goto main

'Program truncated, full program can be found below in txt file
View attachment control panel main.txt
 

hippy

Technical Support
Staff member
Your program in the .txt file does not pass syntax check and, when corrected so it does, the serial routines are never called.

It is not clear exactly what you are hoping for people to check.

The best way to proceed from having written initial code is to run it on the hardware and see how it performs, using SERTXD to report results which should be sent rather than relying on having the slave side of the hardware built.

Your calculation for key code does not appear to be correct. That seems to be in your 'multiply' routine using 'b2 = b0*b1', where b0 can be 1 to 11 (row) and b1 can be 12 to 22 (col). That would give clashes, for example, b0=3 and b1=12 becomes 36, and so does b0=2 and b1=18.
 

techElder

Well-known member
danners430, for someone besides the programmer to know what is going on in a program takes some extra effort. When soliciting help, you will get more valuable help when you can make the program more readable.

One way to make your program more readable for others (and you in the future) is to use the PICAXE editor's SYMBOL command. For instance, your code ...

Code:
	let b0 = 0			'Matrix outputs
	let b1 = 0			'Matrix inputs
	let b2 = 0			'Matrix result
	let b3 = 0			'Serout address byte
	let b4 = 0			'Serout data byte 1
... could be easier to read throughout the program without having to go back to your assignment statements if you did them like this ...

Code:
SYMBOL matrixOut = b0
SYMBOL matrixIn = b1
SYMBOL matrixRes = b2
SYMBOL serOutAddr = b3
SYMBOL serOutData1 = b4

	let matrixOut = 0		'Matrix outputs
	let matrixIn = 0			'Matrix inputs
	let matrixRes = 0		'Matrix result
	let serOutAddr = 0		'Serout address byte
	let serOutData1 = 0		'Serout data byte 1
...

multiply:
	matrixRes = matrixOut * matrixIn		' Multiply the addresses of the output & input together to give a unique ID of button pressed
	matrixRes = matrixRes - 10			' Take 10 away to make smallest possible address 1.
	if matrixRes = 0 then main
...
 
Cheers for the help guys... I'm by no means a professional programmer, so I'm learning :)

I'm working on the multiplication issue just now, and I'll tidy up the program in due course with symbols etc. to make it readable.

Thanks!
 

westaust55

Moderator
I'm working on the multiplication issue just now, and I'll tidy up the program in due course with symbols etc. to make it readable.
It is far better to start defining alias names for variables with SYMBOL statements up front rather than at the end.
That way when you need help, is is earlier for those helping (for free) to quickly understand and give guidance.

Many here are NOT professional programmers but have learnt over time.
 
Last edited:

hippy

Technical Support
Staff member
Code:
'Chip used is a PICAXE 28X2
'	11x Matrix outputs  B.0-7, C.5-7
'	11x Matrix Input    A.0-7, C.2-4
Note that the 28X2 does not have A.5, A.6 or A.7 pins, and A.4 is output only; Download Serial Out.

For a master requiring serial in and out, the largest matrix supported by a 28X2 would appear to be 9 x 10 giving 90 buttons, though that could be doubled to 180 by using a diode matrix and more complicated code.

How many buttons do you need ? 8 x 11 would be easier to code for if you only needed 88 buttons.
 
hey guys,

progress has been made. Or, to be more accurate, the program has been re-written from the ground up. I think I've made it user-friendly: I've changed all the variable labels to symbols, with all the relevant pinouts etc. listed at the start of the program.

I've gone up to a 40X2 and a 15x15 button matrix, and I've simplified the description for the program. So, here goes!

The picaxe takes inputs from the 15x15 button matrix. Each row and column is numbered: rows 0-14 and columns 1-15. Each button in the matrix has an ID, determined by pushing the column ID into the high and the row ID into the low nybble of the "matrixres" variable.
Once a button press has been detected, the picaxe carries out a set of instruction, or script, which has been written and inserted into the program in the slot for the button's ID. (None have been written yet!) This script can include sending serial data using the "transmit" sub-procedure. This first ensures the receiving chip is listening for serial inputs, then sends the commands.

Hopefully I've been able to give an insight of my programming vision - Really, all I am asking to be checked is my logic surrounding the matrix, which is annoyingly complicated!

View attachment control panel main.bas

Cheers guys
 
Last edited:

hippy

Technical Support
Staff member
Hopefully I've been able to give an insight of my programming vision - Really, all I am asking to be checked is my logic surrounding the matrix, which is annoyingly complicated!
It's not quite how I would do it, and it can be heavily optimised, but it looks like the logic is fine to me, though you likely need to put a 'matrixin=0' and a 'matrixres=0' at the start of your 'main:' loop.

The biggest risk with the code is if you inadvertently have multiple key presses and end up shorting one output high to an output low. Ideally you only want to have one line as an output at a time.
 
Hi Hippy,

I'm going to have 1k resistors on all inputs, and diodes protecting the outputs... Just in case! My only question would be regarding the interfacing manual, where buttons are listed as needing a pulldown resistor. Is that still needed in such a system?
 

hippy

Technical Support
Staff member
Yes, all input pins will require pull-downs. Current limiting resistors on all output pins will protect outputs from high to low shorts, but diodes will not.
 

westaust55

Moderator
Yes, resistors all around.

For the inputs, I suggest 10 kOhm pull down to 0 volts.

For the outputs they must be in series with the output.
If every output has a 150 ohm resistor then a short between two has a total of 300 Ohms which will limit the current in the event of a high to low short To a max of 16 mA. (Within the capabilities of the PICAXE I/O.
 
Brilliant. Im still developing the concept, but hopefully I should have something to post in completed projects sooner or later!
 
Top