Expanding outputs over multiple PICAXE chips

ValueAdd

Senior Member
Multiple picaxe chips

While the solution may not yet have been reached, I have been finding the information in this thread very informative on how to use the i2c between picaxe chips.
 

jsch2603

New Member
Some Test Results

Just thought I’d post perhaps a final update with regards to this subject in order to disclose what my findings were. Please take into consideration that I am still a “newbie” at this and am describing events to the best of my comprehension at this time.

Findings:
Overall (with the helpful input from other members), I’ve learned a lot in a short while, and in looking back to whereabouts’ a month ago, if one were to ask me what a PICAXE was, I would have told them to have a go on out to the shed. It’s now, with a significant sense of accomplishment, that I’m able to successfully perform the following key actions as a result of said input and further personal experimentation and testing:
1. Establish I2C communications between a Master and (2) Slave 40X1 PICAXE chips by utilizing the hi2csetup and hi2cout commands. Also proper usage of the slavename (address), location (within the Slave’s scratchpad memory) and [newslave] parameters.
2. Proper usage of the “get” command at the Slave 40X1 along with the Slave’s scratchpad “location” parameter.
3. Configure the available portc outputs on both Master and Slaves so as to not be affected (apparently) by the I2C comms. (see sample code portc initialization strings).
4. Directly write to the Master’s portb and portc outputs (less of course pins 3 & 4 of portc, which are used for the I2C comms.) with the following conditions (as they apply to driving LED’s):
a. Alternating port and inter-port flashing
b. Sequential port and inter-port flashing
c. Simultaneous inter-port steady-state and flash
5. In-directly write to both Slave’s portb and portc outputs via I2C (less of course pins 3 & 4 of portc, which are used for the I2C comms.), with the conditions as stated above for the Master, but with the following exception regarding item “c”:
a. Ditto
b. Ditto
c. Near simultaneous inter-port steady-state and flash.
Note: I say “near” because it was necessary (with the way I was attempting to write to both ports simultaneously) to include a short pause (70-100ms) between the writes (hi2cout commands) in order for the setintflags interrupt on the slave to properly detect each ports transition. Perhaps further refinements to my code utilizing other commands and/or practices that I am not yet aware of, or perhaps incorporating further use of words, the hi2clast variable, etc. would eliminate the need for such pauses in the code -Time will tell.
6. Use of the setintflags system variable for polling writes from the Master.
7. Gain insight into use of the hi2cflag and hi2clast variables. See observation notes to follow.
8. Transmit serial data from both Master and Slave to the terminal (computer) screen.

Related Observations:
1. The earlier code supplied by Technical for establishing communications between Master and Slaves proved useful, but did not go as far as to address the possibility of writing to portc on the Slave’s, and the details necessary for simultaneously / sequentially / alternately writing to both ports b and c (when configured as outputs). Nonetheless, the code provided a good start and was quite helpful.
2. Also, the earlier code snippet provided by Tarzan, provided insight into the operation of the setintflags system interrupt, the hi2cflag and the hi2clast variables, as well as portc initialization in light of I2C. The only apparent shortcoming (perhaps in-part due to my limited PICAXE programming experience to date) was that due to the limitation of the setintflag variable only being able to interrupt on one input (scratchpad write) condition (i.e. get hi2clast, b0), I was unable to direct these bytes to both ports b and c successively. What I wound up doing in my case at the slave was to get the 2 scratchpad written bytes as a word (to comply with the "single allowed input" by the system interrupt), then extract those two bytes and direct them to the appropriate port. Again, maybe there’s more that I need to learn about using this interrupt to this extent if it is at all possible.
3. Portc limitations in addition to when being designated as outputs in conjunction with I2C usage appears to pose some inherent obstacles, which may discourage one from going this route. This post simply serves as notice that within reason portc (along with port b for that matter) can be expanded over multiple PICAXE (40X1 in my case) chips.
4. Apparently, “Symbol” assignments cannot be used with Porta inputs.
5. The simulator was a bit limited with this application (I2C communications between PICAXE chips) in that one couldn’t readily observe slave scratchpad values from the master; no concern though as I temporarily made use of the “put” command to duplicate the Slave’s scratchpad values on the Master.
6. Putting my laptop in standby, and thus the USB communications to the PICAXE, seemed to have an affect upon program execution/output, particularly when sertxd commands were executed, but I cannot confirm this for sure and instead just moved on in the interest of time; it was not a big issue for me at that point.
7. Quite by accident, it was interesting to note that with the PICAXE chip powered OFF, a change of input condition (e.g. applying high, in my case) caused the chip’s program to execute and the outputs to drive the test LED’s as well as causing the I2C clock and data lines to activate – in a sense, back-feeding the internal circuitry.

In Conclusion:
Even though I’ve achieved roughly 90% of my applications desired results to date by expanding outputs across these three 40X1 chips using I2C, I will be conducting future experiments utilizing, and most likely making the switch to a single 40X1 in combination with I/O expanders driving Darlington arrays. All-in-all, even at this somewhat advanced stage, having previously rendered driver board artwork under the presumption that I would be using it in conjunction with the (3) AXE022 boards, it still would appear much more practical in my particular situation by:
a. Reducing cabling requirements (by virtue of I2C).
b. Reducing from (3) AXE022 project boards and 40X1’s to just (1), in addition to a custom driver I/O driver board, providing me with a couple of spare 40X1’s / AXE022’s for possible future projects.
c. More cost effective solution (initially, and if not done after the fact as was in my case) as opposed to using two additional 40X1 Slave’s for the purpose of I/O expansion only.
d. Hopefully reducing the need for introducing pauses between writes (this may just be a lack of coding experience on my part).
e. And a number of other things that don’t come to mind at this time.

I thought it might be helpful to provide some working code snippets summarizing my findings; generic samplings derived from my application program for both the Master and (2) Slave 40X1’s. I’ve stripped-out much of the “symbology” and only a couple of routines are supplied exemplifying writes to all local (Master) and Slave ports. Take care to note that some alternative command strings were left in for reference purposes only and thus have been commented out (preceded with a semicolon). Hopefully, this will provide some fundamental guidance for one perhaps looking to control outputs across PICAXE’s involving I2C. Cheers!

NOTE: DUE TO CHARACTER RESTRICTIONS, CODE SNIPPETS (ALTHOUGH SOMEWHAT LARGE) WILL APPEAR IN SUBSEQUENT POSTS

General Comments / Questions:
1. I understand that perhaps it is beyond the scope of RevEd to incorporate such information in manual 1 (or some other publication), but in hindsight, I think it would be helpful for individuals such as myself, to be made aware as to the availability of complementary I2C slave devices (i.e. I/O Expanders, etc.) that would further illuminate the PICAXE experience.
2. I’ve read some posts concerning the possibility of a beginner’s forum. Although I think this to be a good idea for the future, I’m not sure as to how one would go about distinguishing; in other words, where one would draw the line between various levels of experience. I have found the present structure to be very helpful as a newbie, but often sympathize with those more experienced that have perhaps seen the same fundamental issues questioned over-and-over again.
3. It seems unfortunate that more than one interrupt (setint) cannot be accommodated, maybe with good reason. I have several input conditions that I would like to trigger interrupts for a quicker response. Might there be other programming techniques that I may not be aware of in this regard?
4. I have come across a few, but if anyone knows a good thread regarding the implementation/coding and/or link to single or multi-chip PCB artwork for 16-bit I/O expanders (p/n MCP23016 or 17), please advise. I currently have MCSs’ app. note AN #139 pertaining to the 16. I any case, I will figure out in time. Thanks!
 

Attachments

Last edited:

jsch2603

New Member
40X1-1 Master (Part 1 of 3)

Code:
;40X1-1 Master - FOR REFERENCE ONLY: Errors may have occurred in transposing this code for post, but basic simulator tests appear functional.
;To sample, copy and paste all three (3) Master parts (code snippets) together.  For convenience, only inputs 3 & 4 (portd) and porta analog
;inputs 1 & 2 (configured as digital inputs) are used,  Note: On the simulator, these porta inputs require a value >= 130 to be high.

;#com 4						; Directive: Set the serial COM port to 4 for downloading

#picaxe 40X1 					; tested on A.2. Directive: #picaxe 08/08m/14m/20m/18/18a/18x/28/28a/28x/28x1/28x2/40x/<40x1>/40x2
						; Set the compiler mode. This directive also automatically defines a label of the
						; PICAXE type e.g. #picaxe 08m is also the equivalent of #define 08m. If no
						; #picaxe directive is used the system defaults to the currently selected PICAXE
						; mode (View>Options>Mode menu within Programming Editor).

#terminal 4800					; Directive: #terminal off/300/600/1200/<4800>/9600/19200/38400 Programming Editor Only
						; Config the Serial Terminal to open after a download (at selected baud rate)
						
setfreq em4					; for 28X1, 40X1:
						; internal: k31,k125,k250,k500,m1, m2, m4, m8
						; <external>: <em4>, em8, em10, em16, em20

let dirsc = %11100111				; direct the (3) portc LSB's and MSB's as outputs&#8217;
pinsc = %00000000				; set all portc pins low
; high portc 1,2,3,5,6,7			; alternate method for directing designated portc pins as outputs (40X1?)

hi2csetup i2cmaster, %10110000, i2cslow, i2cbyte

						; HI2CSETUP I2CMASTER, slaveaddress, mode, addresslen
						;-slaveaddress: is the i2c slave address (Note: %10100000 reserved for future EEPROM)
						;-mode: is the keyword i2cfast (1MHz) i2cmedium (400kHz) or
						; i2cslow (100kHz)
						;-addresslen: is the keyword i2cbyte or i2cword
						; Note that this is the &#8216;addressing method&#8217; used by the
						; i2c device (i.e. some eeproms use a byte address,
						; some use a word address). It is NOT the length of data
						; returned by the hi2cin command, which is always a byte

symbol mat = pin3				; rename input pin3 &#8216;mat&#8217;
symbol hit = pin4				; rename input pin4 &#8216;hit&#8217;

symbol s1_portb = b0				; rename output variable b0 &#8216;s1_portb&#8217; (slave 1, portb)
symbol s1_portc = b1				; rename output variable b1 &#8216;s1_portc&#8217; (slave 1, portc)
symbol s2_portb = b2				; rename output variable b2 &#8216;s2_portb&#8217; (slave 2, portb)
symbol s2_portc = b3				; rename output variable b3 &#8216;s2_portc&#8217; (slave 2, portc)

symbol hit_counter = b10 			; define a &#8216;hit_counter&#8216; using variable b10
symbol fire_counter = b11 			; define a &#8216;fire_counter&#8216; using variable b11
symbol sesr_counter = b12	 		; define a &#8216;sesr_counter&#8216; using variable b12
symbol sysr_value = b13				; define   &#8216;sysr_value&#8216; (constant) using variable b13

setint %00010000,%00010000			; activate interrupt when &#8216;hit&#8216; (pin4) goes high

pause 1000

main:						; make a label called &#8216;main&#8217;

;MASTER PORTS B & C OUTPUT EXAMPLE ---------------------------------------------------------------
;The following do loop (simplified with many switch combos, removed) will alternately flash all
;portb outputs and outputs 0,1,2 of portc when the mat input is set high, then all OFF when low.

do							; start a do loop
	if mat = 1 then					; if &#8216;mat&#8216; (pin3) input is high then...	
		let pins = %11111111			; set all outputs on portb high
;sertxd ("The value of portb is... ",#portb,13,10)	; transmit portb number value to terminal
		let portc = %00000111			; set (3) LSB outputs on portc high
;sertxd ("The value of portc is... ",#portc,13,10)	; transmit portc number value to terminal
		pause 500 				; wait for 0.5 second
		let pins = %00000000			; set all outputs on portb low
;sertxd ("The value of portb is... ",#portb,13,10)	; transmit portb number value to terminal	
		let pinsc = %00000000			; set all outputs on portc low
;sertxd ("The value of portc is... ",#portc,13,10)	; transmit portc number value to terminal
		pause 500 				; wait for 0.5 second
	loop until mat = 0				; loop until mat is low
	endif

;SLAVE 2 PORTB OUTPUT EXAMPLE ---------------------------------------------------------------------

	if porta pin0 = 1 then gosub sessend		; sub to sessend if porta, pin0 input is high
							; Note: This also demonstrates the use of the
							; analog porta inputs as digital inputs.
							; A value >=130 (on the simulator's input)
							; sets the porta input high.
;SLAVE 2 PORTC OUTPUT EXAMPLE ---------------------------------------------------------------------

	if porta pin1 = 1 then
	gosub fireseq					; sub to fireseq if porta, pin1 input is high
	else						; if porta, pin1 input is low then
	let s2_portc = %00000000			; set all outputs on portc low
	hi2cout [%11000000],1,(s2_portc)		; write s2_portc (b3) value to slave 2 scratchpad reg. 1
	let fire_counter = %00000000			; reset fire_counter (b11)
	endif

	goto main

;MASTER TO SLAVE 1 INTERRUPT SUBROUTINE -----------------------------------------------------------

interrupt:
	gosub hitseq						; sub to hitseq				
	if hit = 1 then						; if &#8216;hit&#8216; (pin4) = 1 then...
	goto interrupt						; loop here until interrupt clears
	else let s1_portb = %00000000				; set output group 00 thru 07 (slave 1, portb) low
	hi2cout [%10110000],0,(s1_portb)			; write s1_portb (b0) value to slave 1 scratchpad reg. 0
;sertxd ("The value of b0 is... ",#s1_portb,13,10)	; transmit s1_portb (b0) number value to terminal
	pause 100;50						; I2C simultaneous port write delay
	let s1_portc = %00000000				; set output group 08 thru 10 (slave 1, portc) low
	hi2cout [%10110000],1,(s1_portc)			; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc (b1) number value to terminal
	pause 100;50
	let hit_counter = 0					; reset hit_counter
	endif
	setint %00010000,%00010000				; reactivate interrupt
	goto main
 
Last edited:

jsch2603

New Member
40X1-1 Master (Part 2 of 3)
Code:
;SLAVE 1 PORTB & PORTC OUTPUT SUBROUTINE ----------------------------------------------------------
;The following hitseq sub will sequentially turn ON and OFF bits 0-7 of portb and bits 0-2 of portc,
;it will then flash these bits 2x near simultaneously and then they will switch to a steay ON state.
;(Note portc I2C pins 3 and 4 are excluded)

hitseq:								; make a label called &#8216;hitseq&#8217;
	if hit_counter = 3 then return			; prevent re-triggering of &#8216;hitseq&#8217; sub
	endif
	let s1_portb = %00000000				; set output group 00 thru 07 (slave 1, portb) low
	hi2cout [%10110000],0,(s1_portb)			; write s1_portb (b0) value to slave 1 scratchpad reg. 0
;sertxd ("The value of b0 is... ",#s1_portb,13,10)	; transmit s1_portb (b0) number value to terminal
	pause 100;50;10						; I2C simultaneous port write delay
	let s1_portc = %00000000				; set output group 08 thru 10 (slave 1, portc) low
	hi2cout [%10110000],1,(s1_portc)			; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc (b1) number value to terminal
	pause 200						; wait for 0.2 second
	let s1_portb = %00000001				; set output group 00 high
	hi2cout [%10110000],0,(s1_portb)			; write s1_portb (b0) value to slave 1 scratchpad reg. 0
;put 0,s1_portb							; "put" commands (when included) serve to display the
								; variable value in the simulators scratchpad data window
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00000010				; set output group 01 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00000100				; set output group 02 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00001000				; set output group 03 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00010000				; set output group 04 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00100000				; set output group 05 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %01000000				; set output group 06 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %10000000				; set output group 07 high
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200
	let s1_portb = %00000000				; set output group 07 low
	hi2cout [%10110000],0,(s1_portb)
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)
	pause 200						; wait for 0.2 second
	let s1_portc = %00000001				; set output group 08 high
	hi2cout [%10110000],1,(s1_portc)			; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;put 1,s1_portc		
;sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc (b1) number value to terminal
	pause 200						; wait for 0.2 second
	let s1_portc = %00000010				; set output group 09 high
	hi2cout [%10110000],1,(s1_portc)
;put 1,s1_portc	
;sertxd ("The value of b1 is... ",#s1_portc,13,10)	
	pause 200
	let s1_portc = %00000100				; set output group 10 high
	hi2cout [%10110000],1,(s1_portc)
;put 1,s1_portc
;sertxd ("The value of b1 is... ",#s1_portc,13,10)
	pause 200
	let s1_portc = %00000000				; set output group 10 low
	hi2cout [%10110000],1,(s1_portc)
;put 1,s1_portc
;sertxd ("The value of b1 is... ",#s1_portc,13,10)
	pause 200
	for hit_counter = 1 to 2 				; start a for...next loop
		let s1_portb = %11111111			; set output group 00 thru 07 high
		hi2cout [%10110000],0,(s1_portb)		; write s1_portc (b1) value to slave 1 scratchpad reg. 0
;	put 0,s1_portb
;	sertxd ("The value of b0 is... ",#s1_portb,13,10)	; transmit s1_portb (b0) number value to terminal

		pause 70;50					; I2C simultaneous port write delay
								; Note: >=70ms is req. for slave ports b & c
								; to flash simultaneously w/USB conn. or not
								
		let s1_portc = %00000111			; set output group 08 thru 10 high	
		hi2cout [%10110000],1,(s1_portc)		; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;	put 1,s1_portc
;	sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc (b1) number value to terminal		
		pause 500 					; wait for 0.5 second
		let s1_portb = %00000000			; set output group 00 thru 07 low
		hi2cout [%10110000],0,(s1_portb)		; write s1_portb (b0) value to slave 1 scratchpad reg. 0
;	put 0,s1_portb
;	sertxd ("The value of b0 is... ",#s1_portb,13,10)	; transmit s1_portb (b0) number value to terminal
		pause 100;100					; I2C simultaneous port write delay
		let s1_portc = %00000000			; set output group 08 thru 10 low
		hi2cout [%10110000],1,(s1_portc)		; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;	put 1,s1_portc
;	sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc (b1) number value to terminal			
		pause 500 					; wait for 0.5 second
	next hit_counter 					; end of for...next loop
	let s1_portb = %11111111				; set output group 00 thru 07 high
	hi2cout [%10110000],0,(s1_portb)			; write s1_portb (b0) value to slave 1 scratchpad reg. 0
;put 0,s1_portb
;sertxd ("The value of b0 is... ",#s1_portb,13,10)	; transmit s1_portb (b0) number value to terminal
	pause 100;50						; I2C simultaneous port write delay
	let s1_portc = %00000111				; set output group 08 thru 10 high
	hi2cout [%10110000],1,(s1_portc)			; write s1_portc (b1) value to slave 1 scratchpad reg. 1
;put 1,s1_portc						; wait for 0.1 second
;sertxd ("The value of b1 is... ",#s1_portc,13,10)	; transmit s1_portc  (b1) number value to terminal
	pause 100;50
	return							; return from sub

;SLAVE 2 PORTB OUTPUT SUBROUTINE ------------------------------------------------------------------
;The following sessend sub will sequentially turn ON and OFF bits 0-6 of portb when the Master's porta pin0
;is set high. This continues until this input is set low. Bit7 is a power ON ind. that remains ON in this case,
;Bit2 has intentionally been left low.

sessend:
	let s2_portb = %10000000				; set s2_portc output group 00 thru 06 low, 07 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100;50;10						; I2C simultaneous port write delay
	let s2_portb = %10000001				; set s2_portb output group 00 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100						; wait for 0.1 second
	let s2_portb = %10000010				; set s2_portb output group 01 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100						; wait for 0.1 second
								; note: group 02 (air pressure low) not included
	let s2_portb = %10001000				; set s2_portb output group 03 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100							; wait for 0.1 second
	let s2_portb = %10010000				; set s2_portb output group 04 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100							; wait for 0.1 second
	let s2_portb = %10100000				; set s2_portb output group 05 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100							; wait for 0.1 second
	let s2_portb = %11000000				; set s2_portb output group 06 high
	hi2cout [%11000000],0,(s2_portb)			; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
	pause 100;50,10	

	if porta pin0 = 0 then					; if porta, pin0 input = 0 then...
		let s2_portb = %10000000			; set s2_portb output group 06 low
		hi2cout [%11000000],0,(s2_portb)		; write s2_portb (b2) value to slave 2 scratchpad reg. 0
;sertxd ("The value of b2 is... ",#s2_portb,13,10)	; transmit s2_portb (b2) number value to terminal
		pause 100;50,10
	else goto sessend
	endif
	return
 
Last edited:

jsch2603

New Member
40X1-1 Master (Part 3 of 3)
Code:
;SLAVE 2 PORTC OUTPUT SUBROUTINE ------------------------------------------------------------------
;The following fireseq sub will flash portc bits 0-2,5-7 at a 0.5 second interval 2x, then switch to 
;steady ON (Note I2C pins 3 and 4 are excluded)

fireseq:							; make a label called &#8216;fireseq&#8217;
	if fire_counter = 3 then return			; prevent re-triggering of &#8216;fireseq&#8217; sub
	else
	for fire_counter = 1 to 2 				; start a for...next loop
		let s2_portc = %11100111			; set s2_portc output groups 00,01,02 and 05,06,07 high
		hi2cout [%11000000],1,(s2_portc)		; write s2_portc (b3) value to slave 2 scratchpad reg. 1
	; sertxd ("The value of b3 is... ",#s2_portc,13,10)	; transmit s2_portc (b3) number value to terminal
		pause 500 					; wait for 0.5 second
		let s2_portc = %00000000			; set s2_portc output group 00 thru 07 low
		hi2cout [%11000000],1,(s2_portc)		; write s2_portc (b3) value to slave 2 scratchpad reg. 1		
	; sertxd ("The value of b3 is... ",#s2_portc,13,10)	; transmit s2_portc (b3) number value to terminal
		pause 500 					; wait for 0.5 second
	next fire_counter
	let s2_portc = %11100111				; set s2_portc output groups 00,01,02 and 05,06,07 high
	hi2cout [%11000000],1,(s2_portc)			; write s2_portc (b3) value to slave 2 scratchpad reg. 1
; sertxd ("The value of b3 is... ",#s2_portc,13,10)	; transmit s2_portc (b3) number value to terminal
	endif
	return
 
Last edited:

jsch2603

New Member
40X1-2 Slave 1
Code:
;40X1-2, Slave 1 - FOR REFERENCE ONLY

;#com 4					; Directive: Set the serial COM port to 4 for downloading

#picaxe 40X1 				; tested on A.2. Directive: #picaxe 08/08m/14m/20m/18/18a/18x/28/28a/28x/28x1/28x2/40x/<40x1>/40x2
					; Set the compiler mode. This directive also automatically defines a label of the
					; PICAXE type e.g. #picaxe 08m is also the equivalent of #define 08m. If no
					; #picaxe directive is used the system defaults to the currently selected PICAXE
					; mode (View>Options>Mode menu within Programming Editor).
						
#terminal 4800				; Directive: #terminal off/300/600/1200/4800/9600/19200/38400 Programming Editor Only
					; Config the Serial Terminal to open after a download (at selected baud rate)
						
setfreq em4				; for 28X1, 40X1:
					; internal: k31,k125,k250,k500,m1, m2, m4, m8
					; <external>: <em4>, em8, em10, em16, em20

let dirsc = %11100111			; direct the (3) portc MSB's and LSB's as outputs
let pinsc = %00000000			; apparently setting all portc pins low, but why this works is yet TBD
;high portc 0,1,2,5,6,7			; method of setting portc pins 0,1,2,5,6,7 as outputs but not sure if applies to 40X1

hi2csetup i2cslave, %10110000		; HI2CSETUP I2CSLAVE, slaveaddress
					;-slaveaddress is the i2c slave address
						
ptr = 0					; reset scratchpad pointer to 0

setintflags %01000000,%01000000	; SETINTFLAGS flags,mask - Function: Interrupt on hi2c write (slave mode)
					; The setintflags command causes a polled interrupt on a certain flags byte condition.
; Note: The flags byte is checked	; - flags is a variable/constant (0-255) which specifies flags byte condition.
; between execution of each 		; - mask is variable/constant (0-255) which specifies the mask
; command line in the program,	; The system &#8216;flags&#8217; byte is broken down into individual bit variables.
; between each note of a		; Name 	Special 	Special function
; tune command, and continuously	; flag0-4	reserved
; during any pause command		; flag5 	hserflag 	hserial background receive has occurred
					;<flag6> 	hi2cflag 	hi2c write has occurred (slave mode)
					; flag7 	toflag 	timer overflow flag


main:					; make a label called &#8216;main&#8217;

	pause 2000			; wait for 2.0 seconds (dummy pause)
	goto main

interrupt:
;setintflags off			; Note for SETINT: Only one input pattern is allowed at any time.
					; To disable the interrupt execute a SETINTFLAGS OFF command.
							
	get 0, word w0			; get b0:b1  Note: Getting a word is key as opposed to getting
					; the bytes individually. This is due to the requirement that
					; only one input pattern is allowed at any time upon interrupt.
					; This applies to the SETINT command and appears as well to the
					; SETINTFLAGS command, as is the case here..

;sertxd ("The value of w0 is... ",#w0,13,10)	; transmit word 0 number value to terminal

	outpins = b0			; extract b0 from w0 and output to portb
	
;Note: Pauses between portc & b hic2out commands in Master's code allow for near simultaneous writes
		
	pinsc = b1			; extract b1 from w0 and output to portc
	
;PORTC I2C PIN ERROR SENSING ----------------------------------------------------------------------

	if bit11 = 1 then gosub error		; if w0 bit11 (pin4) is high gosub error
	if bit12 = 1 then gosub error		; if w0 bit12 (pin5) is high gosub error

	hi2cflag = 0				; reset the system flag
	setintflags %01000000,%01000000		; reset the system interrupt

	return

error:						; make a label called &#8216;main&#8217;
	sertxd ("*** ERROR ***",13,10,"DO NOT SEND NUMBER: ",#b1,13,10)
	bit11 = 0				; set portc bit11 (I2C port CL) low
	bit12 = 0				; set portc bit12 (I2C port DA) low
	return
 
Last edited:

jsch2603

New Member
40X1-3 Slave 2
Code:
;40X1-2, Slave 2 - FOR REFERENCE ONLY

;#com 4				; Directive: Set the serial COM port to 4 for downloading

#picaxe 40X1 			; tested on A.2. Directive: #picaxe 08/08m/14m/20m/18/18a/18x/28/28a/28x/28x1/28x2/40x/<40x1>/40x2
				; Set the compiler mode. This directive also automatically defines a label of the
				; PICAXE type e.g. #picaxe 08m is also the equivalent of #define 08m. If no
				; #picaxe directive is used the system defaults to the currently selected PICAXE
				; mode (View>Options>Mode menu within Programming Editor).
						
#terminal 4800			; Directive: #terminal off/300/600/1200/4800/9600/19200/38400 Programming Editor Only
				; Config the Serial Terminal to open after a download (at selected baud rate)
						
setfreq em4			; for 28X1, 40X1:
				; internal: k31,k125,k250,k500,m1, m2, m4, m8
				; <external>: <em4>, em8, em10, em16, em20

let dirsc = %11100111		; direct the (3) portc MSB's and LSB's as outputs
let pinsc = %00000000		; apparently setting all portc pins low, but why this works is yet TBD
;high portc 0,1,2,5,6,7		; method of setting portc pins 0,1,2,5,6,7 as outputs but not sure if applies to 40X1

hi2csetup i2cslave, %11000000	; HI2CSETUP I2CSLAVE, slaveaddress
				;-slaveaddress is the i2c slave address
						
ptr = 0				; reset scratchpad pointer to 0

setintflags %01000000,%01000000	; SETINTFLAGS flags,mask - Function: Interrupt on hi2c write (slave mode)
				; The setintflags command causes a polled interrupt on a certain flags byte condition.
; Note: The flags byte is checked	; - flags is a variable/constant (0-255) which specifies flags byte condition.
; between execution of each 	; - mask is variable/constant (0-255) which specifies the mask
; command line in the program,	; The system &#8216;flags&#8217; byte is broken down into individual bit variables.
; between each note of a	; Name 	Special 	Special function
; tune command, and continuously; flag0-4	reserved
; during any pause command	; flag5 	hserflag 	hserial background receive has occurred
				;<flag6> 	hi2cflag 	hi2c write has occurred (slave mode)
				; flag7 	toflag 	        timer overflow flag


main:					; make a label called &#8216;main&#8217;

	pause 2000			; wait for 2.0 seconds (dummy pause)
	goto main

interrupt:
;setintflags off			; Note for SETINT: Only one input pattern is allowed at any time.
					; To disable the interrupt execute a SETINTFLAGS OFF command.
							
	get 0, word w0			; get b0:b1  Note: Getting a word is key as opposed to getting
					; the bytes individually. This is due to the requirement that
					; only one input pattern is allowed at any time upon interrupt.
					; This applies to the SETINT command and appears as well to the
					; SETINTFLAGS command, as is the case here..

;sertxd ("The value of w0 is... ",#w0,13,10)	; transmit word 0 number value to terminal

	outpins = b0			; extract b0 from w0 and output to portb
	
;Note: Pauses between portc & b hic2out commands in Master's code allow for near simultaneous writes
		
	pinsc = b1			; extract b1 from w0 and output to portc
	
;PORTC I2C PIN ERROR SENSING ----------------------------------------------------------------------

	if bit11 = 1 then gosub error	; if w0 bit11 (pin4) is high gosub error
	if bit12 = 1 then gosub error	; if w0 bit12 (pin5) is high gosub error

	hi2cflag = 0			; reset the system flag
	setintflags %01000000,%01000000	; reset the system interrupt

	return

error:				  ; make a label called &#8216;error&#8217;
	sertxd ("*** ERROR ***",13,10,"DO NOT SEND NUMBER: ",#b1,13,10)
	bit11 = 0			; set portc bit11 (I2C port CL) low
	bit12 = 0			; set portc bit12 (I2C port DA) low
	return
 
Last edited:

westaust55

Moderator
:
:
General Comments / Questions:
1. I understand that perhaps it is beyond the scope of RevEd to incorporate such information in manual 1 (or some other publication), but in hindsight, I think it would be helpful for individuals such as myself, to be made aware as to the availability of complementary I2C slave devices (i.e. I/O Expanders, etc.) that would further illuminate the PICAXE experience.
2. I&#8217;ve read some posts concerning the possibility of a beginner&#8217;s forum. Although I think this to be a good idea for the future, I&#8217;m not sure as to how one would go about distinguishing; in other words, where one would draw the line between various levels of experience. I have found the present structure to be very helpful as a newbie, but often sympathize with those more experienced that have perhaps seen the same fundamental issues questioned over-and-over again.
3. It seems unfortunate that more than one interrupt (setint) cannot be accommodated, maybe with good reason. I have several input conditions that I would like to trigger interrupts for a quicker response. Might there be other programming techniques that I may not be aware of in this regard?
4. I have come across a few, but if anyone knows a good thread regarding the implementation/coding and/or link to single or multi-chip PCB artwork for 16-bit I/O expanders (p/n MCP23016 or 17), please advise. I currently have MCSs&#8217; app. note AN #139 pertaining to the 16. I any case, I will figure out in time. Thanks!
Glad to hear that you have gained great experience with the i2c and have a project working.

wrt your comments/questions:

1. Rev Ed does list some i2c related devices in their i2c tutorial (this is related mainly to a data logger example) and in Manual 2 (for example see page53 in the current/Rev6.5b version of manual 2)
Agree that there is always room however for a few more devices and certainly IO expanders do come up regularly in threads on this forum

2. Not sure that a separate beginners forum would achieve anything more than can be achieve on this forum and just another place for the &#8220;helpful&#8221; members to have to troll.
AS you say where would one draw the line. There are newbies to PICAXE who already have vast electronic experience, there are newbies who have difficulty understanding the basics (but they are here and can be guided) and even some experienced members sometime may want help on what is a relatively simple topic they have not previously covered.

3. I agree. IMHO the PICAXE Interrupt scheme would be far better using a form of OR function rather than the current AND function.

4. BJCKiwi has a code snippet that he has already pointed you towards


and finally,
it is good to see your code in the above posts well formatted and commented.
Far easier for all to read and (most) to understand quickly - full marks there
 
Last edited:

Jeremy Leach

Senior Member
Re the interrupt question ... you can use diodes and a resistor to create a simple OR gate (or an AND gate) and then feed this into an Input, and have an interrupt fire on this input. Then make the interrupt routine react according to the exact pin conditions.
 
Top