Bean's SX28 8x8 PWM Code and SX28 Addressable
Hey Gang!
I would like to see if it's possible to make Bean's SX28 8x8 PWM code so that it makes the SX28 addressable. I would like to use more than one processor for more outputs, actually at least 3 SX28's one for red, green and blue.
I didn't post the code without getting Beans ok! Bean is it ok to post your code?
Thanks,
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I would like to see if it's possible to make Bean's SX28 8x8 PWM code so that it makes the SX28 addressable. I would like to use more than one processor for more outputs, actually at least 3 SX28's one for red, green and blue.
I didn't post the code without getting Beans ok! Bean is it ok to post your code?
Thanks,
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Comments
Bean
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
www.iElectronicDesigns.com
·
I would appreciate any ideas and help!
Thanks,
Kevin
' ========================================================================= ' ' File...... PWM64.SXB ' Compiler.. SX/B Version 1.22 ' Purpose... 64 Multiplexed Channels of PWM (For LED matrix control) ' Author.... Hitt Consulting ' E-mail.... [url=mailto:terry@hittconsulting.com]terry@hittconsulting.com[/url] ' Started... June 15, 2005 ' Updated... ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' Accepts serial data at 9600 baud and provides 64 channels of duty cycle modulated PWM ' Serial data is sent with a header of "!PWM" then 64 bytes of data (0=full off, 255=full on) ' ' OSC1&2 = 50Mhz resonator ' Port RA.3 = Serial input ' Port RB = Rows 0 to 7 (Active High) ' Port RC = Column 0 to 7 (Active High, use NPN transistor as column driver) ' ' 10K ' /MCLR -/\/\/\----- Vdd Pin ' ' 10K ' RA.3 -/\/\/\-----< Serial Input (9600 baud 8N1 Inverted) ' ' 220 Ohm ' RB.0 -/\/\/\-----> PWM Output Row 0 ' ' 220 Ohm ' RB.1 -/\/\/\-----> PWM Output Row 1 ' ' 220 Ohm ' RB.2 -/\/\/\-----> PWM Output Row 2 ' ' 220 Ohm ' RB.3 -/\/\/\-----> PWM Output Row 3 ' ' 220 Ohm ' RB.4 -/\/\/\-----> PWM Output Row 4 ' ' 220 Ohm ' RB.5 -/\/\/\-----> PWM Output Row 5 ' ' 220 Ohm ' RB.6 -/\/\/\-----> PWM Output Row 6 ' ' 220 Ohm ' RB.7 -/\/\/\-----> PWM Output Row 7 ' ' 1K Ohm ' RC.0 -/\/\/\-----> Column Output 0 (To base of NPN column driver) ' ' 1K Ohm ' RC.1 -/\/\/\-----> Column Output 1 (To base of NPN column driver) ' ' 1K Ohm ' RC.2 -/\/\/\-----> Column Output 2 (To base of NPN column driver) ' ' 1K Ohm ' RC.3 -/\/\/\-----> Column Output 3 (To base of NPN column driver) ' ' 1K Ohm ' RC.4 -/\/\/\-----> Column Output 4 (To base of NPN column driver) ' ' 1K Ohm ' RC.5 -/\/\/\-----> Column Output 5 (To base of NPN column driver) ' ' 1K Ohm ' RC.6 -/\/\/\-----> Column Output 6 (To base of NPN column driver) ' ' 1K Ohm ' RC.7 -/\/\/\-----> Column Output 7 (To base of NPN column driver) ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSCHS2, TURBO, STACKX, OPTIONX, BOR42 FREQ 50_000_000 ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- SerialInPin VAR RA.3 ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- Baud CON "N11034" ' Adjusted baud rate for 9600 baud incoming 9600/0.870 ' This adjustment is need because the interrupt uses ' 130 cycles every 1000 clocks. So the main code only ' gets 870 cycles of every 1000 clocks. ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- ' Variables for PWM Interrupt Column VAR BYTE ' 1,2,4,8,16,32,64,128 DataPlace VAR BYTE ' Pointer to PWM values PWM_Count VAR BYTE PWM_Values0 VAR BYTE (8) PWM_Values1 VAR BYTE (8) PWM_Values2 VAR BYTE (8) PWM_Values3 VAR BYTE (8) PWM_Values4 VAR BYTE (8) PWM_Values5 VAR BYTE (8) PWM_Values6 VAR BYTE (8) PWM_Values7 VAR BYTE (8) ' Variables for main code Count VAR BYTE SerialData VAR BYTE ' Set by subroutine "GetSerialChar" ' ------------------------------------------------------------------------- INTERRUPT ' ------------------------------------------------------------------------- ISR_Start: ' Entry and Exit code (37) cycles ' (93+37=130) cycles. NOTE: each path through the interrupt routine should be the ' same number of cycles, so the SERIN command works properly. ASM INC PWM_Count ' (1) Adjust the PWM count ' If the PWM value for each channel is less than ' PWM_Count then it should be high, othewise it ' should be low. JZ :AdjustColumn ' (2/4) NOP ' (1) JMP $+1 ' (3) JMP $+1 ' (3) JMP $+1 ' (3) JMP :ColumnOk ' (3) :AdjustColumn ADD DataPlace,#$08 ' (2) RL Column ' (1) JC :ResetColumn ' (2/4) MOV W,#$10 ' (1) SB DataPlace.4 ' (1/2) ADD DataPlace,W ' (1) JMP :ColumnOk ' (3) :ResetColumn MOV Column,#1 ' (2) MOV DataPlace,#PWM_Values0 ' (2) :ColumnOk MOV RC,Column ' (2) MOV __PARAM4,PWM_Count ' (2) Make copy of PWM_Count in global memory MOV FSR,DataPlace ' (2) Set FSR to address of 1st element of PWM values CJA IND,__PARAM4,:HIGH_B0 ' (4/6) CLRB RB.0 ' (1) JMP :DONE_B0 ' (3) :HIGH_B0 SETB RB.0 ' (1) NOP ' (1) :DONE_B0 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B1 ' (4/6) CLRB RB.1 ' (1) JMP :DONE_B1 ' (3) :HIGH_B1 SETB RB.1 ' (1) NOP ' (1) :DONE_B1 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B2 ' (4/6) CLRB RB.2 ' (1) JMP :DONE_B2 ' (3) :HIGH_B2 SETB RB.2 ' (1) NOP ' (1) :DONE_B2 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B3 ' (4/6) CLRB RB.3 ' (1) JMP :DONE_B3 ' (3) :HIGH_B3 SETB RB.3 ' (1) NOP ' (1) :DONE_B3 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B4 ' (4/6) CLRB RB.4 ' (1) JMP :DONE_B4 ' (3) :HIGH_B4 SETB RB.4 ' (1) NOP ' (1) :DONE_B4 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B5 ' (4/6) CLRB RB.5 ' (1) JMP :DONE_B5 ' (3) :HIGH_B5 SETB RB.5 ' (1) NOP ' (1) :DONE_B5 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B6 ' (4/6) CLRB RB.6 ' (1) JMP :DONE_B6 ' (3) :HIGH_B6 SETB RB.6 ' (1) NOP ' (1) :DONE_B6 INC FSR ' (1) CJA IND,__PARAM4,:HIGH_B7 ' (4/6) CLRB RB.7 ' (1) JMP :DONE_B7 ' (3) :HIGH_B7 SETB RB.7 ' (1) NOP ' (1) :DONE_B7 ENDASM ISR_Exit: RETURNINT 250 ' Prescaler at 1:4 = 1000 cycles or 20uSec = 256*20uSec=5.12mSec or 195 Hz ' ========================================================================= PROGRAM Start ' Allow startup code to zero PWM values ' ========================================================================= ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- GetSerialChar SUB 0 ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: TRIS_B=%00000000 ' All outputs TRIS_C=%00000000 ' All outputs ' Setup so at next interrupt will restart at column 0 PWM_Count = 255 DataPlace = PWM_Values7 Column = 128 ' Enable RTCC interrupt OPTION=$81 ' Enable RTCC interrupts, RTCC Prescaler = 1:4 Main: ' Wait for "!PWM" header GetSerialChar IF SerialData <> "!" THEN Main GetSerialChar IF SerialData <> "P" THEN Main GetSerialChar IF SerialData <> "W" THEN Main GetSerialChar IF SerialData <> "M" THEN Main ' Get Data for 64 PWM channels FOR Count=0 TO 7 GetSerialChar PWM_Values0(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values1(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values2(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values3(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values4(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values5(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values6(Count)=SerialData NEXT FOR Count=0 TO 7 GetSerialChar PWM_Values7(Count)=SerialData NEXT ' Do it again GOTO Main ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- GetSerialChar: SERIN SerialInPin,Baud,SerialData RETURN▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The bigger question to decide is if you want each SX to be hardware addressable or have the address encoded permanantly in firmware. The former would require that you use some pins along with jumpers/dip switch to "read" a hardware address. The latter is more flexible and takes no pins, but you would have to download a slightly different version of the firmware to each chip (the only difference in each version would be the address).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
So this would limit my number of boards to 2 max with 3 sx's.
Thanks for the response! I must have posted at the same time.
Any ideas as how to do this by hardware, let's say I want to use dip switches. I guess the other idea is·could it be setup as board 1,2,3 etc and then each board chip have it's own address. If I had any number of boards the chips on each board could have the same address but the main address would be the board 1,2,3. Maybe this isn't possible unless I was using serial comunications from a main(master) sx28 to the other 3 pwm sx's on the board. I plan on just the 3 sx's for now and if i was to make the board stand alone it would then require a master sx.
Regards,
Kevin
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (DigitalDj) : 3/3/2008 3:26:54 AM GMT
If you want a dip-switch/jumper hardware address (so that firmware is same for all chips) then I think you would be limited to 8 chips on one wire, since you only have 3 pins avail. for addressing.
For the latter, all you would need to do is wire dip-switches (or jumpers/headers) to RA.0...RA.2 so that the switch/jumper selection sends a 5v high or 0v low to the pin. On reset, the firmware reads the state of the 3 address pins to see what it's own address is, then saves that info in a variable (actually, you don't even need the variable -- you could just read the 3 pins every time you need to check the address).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Also is standard rs232 from the computer serial port inverted or non inverted?
HELP!
Thanks,
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (DigitalDj) : 3/6/2008 2:15:35 AM GMT
!PWM is plain old ASCII.
The remaining data is sent as raw binary values. You need to send 64 bytes of data, one for each LED.
Thanks,
PeterM
I guess the problem I am having is how to send mixed data.
What is a good program to use for sending the serial info?
Thanks,
kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (DigitalDj) : 3/6/2008 3:15:40 AM GMT
Post Edited (Henrik) : 3/6/2008 8:20:52 AM GMT
realterm.sourceforge.net/
You can type a series of numbers and it can send them as either ASCII or numbers. I was most recently using it for testing an LCD backpack I was working with. The backpack used values below 32 as control characters. It was super easy to use RealTerm to send the control number as numbers and thensend the printable text as ASCII.
Thanks,
PeterM
Thanks, I will give that a try. I did find out that it needs to be sent in ascii but the values have to be sent in the equivelant ascii characters.
With your suggested terminal program sounds like it·solves the difference.
I had to order a resonator for the 16pwm code and I am waiting on trying that, though I may just go ahead and try the code listed above, I have a resonator for it.
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You said, "I did find out that it needs to be sent in ascii but the values have to be sent in the equivalent ascii characters." I think you may need a little more clarity on this issue.
Actually, it doesn't "need" to be sent in ASCII. The fact that you're sending the ASCII equivalent values means you're sending raw binary but using the mechanism of ASCII equivalent characters to send them via a terminal program. If you wrote your own program on the PC to talk to the PWM board, you'd just be sending binary values. You wouldn't bother doing some conversion from binary to ASCII as you could just send binary.
The only reason ASCII enters the equation is that you're using a terminal emulator and not a custom program. As I mentioned in the previous post, terminal emulators typically stink at sending binary data. RealTerm is the only one I have seen that is any good at sending binary at all, although I'm sure there are others.
Good luck with the project.
Thanks,
PeterM
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Hex is binary is decimal. Huh? In other words, all three of those are simply different ways of expressing a number using a different base. Hex is base 16, binary is base 2, and decimal is base 10. All of that is simply stuff we humans use to make things easier to read/write/understand.
When I say "sending binary data", I'm simply referring to sending 8 bits where the value of the eight bits equals the numerical value you want to send. For example, if you want to send the number 123 to your pwm board, you don't send the string "123", you send the 8 bits of data that represent the number 123.
In binary, 123 = 01111011
In hex, 123 = $7B
You mention sending hex in a VB program. The question is are you sending a hex string or a hex value? If it's a hex string, then when you want to send 255 you send the actual character "$" followed by "F" and followed by another "F". This would be sending the hex string "$FF". that's three bytes of data to send a single value. In addition, whatever receives that string has to decode the string an figure out what number it represents. Conversely, if you sent a hex value, you would send just one byte of data, and all eight data bits coming out of the UART have a value of 1. The device receiving it doesn't have to decode that value because it is the number 255, not a string representation of it.
I hoe this makes sense. It sounds like you might still be hazy on the difference between sending a string and sending a number, regardless of what base it is in. I just want to make sure it's clear before you drive yourself crazy. See the recent thread on this forum about the serial inkjet printer to see what kind of frustration you can have if you're not clear about this issue.
Thanks,
PeterM
Sorry I didn't get a email that there was a reply to the thread. Thanks for explaining and yes i'm a little hazy on the serial stuff. I now know to send a string it is $FF for 255 and requires 3 bytes which is what I don't want to do, correct? Since I can send ASCII to the board then I can truly send !PWM, 255, 255, 255 etc. correct?
I attached the code from the VB6 example that a friend of mine & I modified from other code.
The serial code is setup so when the sliders are changed it automatically sends an update to the SX. Everything that is commented is just the old code. I haven't tried this as I am waiting on a 20mhz resonator.
'Dim SX28Cmd(15) As Integer Private Sub Adjust_Change(Index As Integer) SetVolt Index End Sub Private Sub SetVolt(Index As Integer) 'Dim cmd As Integer Dim duty As Integer Dim voltage As Single 'cmd = SX28Cmd(Index) 'duty = -Adjust(Index).Value 'voltage = 5# * duty / 256# Dim o$ 'will hold 16 consecutive value bytes Dim i% For i = 0 To 15 duty = -Adjust(i).Value voltage = 5# * duty / 256# o$ = o$ + Chr$(duty) Volt(i) = Format(voltage, "0.0") Next If MSComm1.PortOpen = True Then MSComm1.Output = "!PWM" + o$ 'Else 'Beep End If 'Volt(Index) = Format(voltage, "0.0") End Sub Private Sub Adjust_Scroll(Index As Integer) SetVolt Index End Sub Private Sub CloseBtn_Click() End End Sub Private Sub Combo1_Change() BreakConnect MSComm1.CommPort = Combo1.ItemData(Combo1.Index) End Sub Private Sub MakeConnect() Dim i As Integer On Error Resume Next MSComm1.PortOpen = True Connect.Caption = "&Disconnect" MSComm1.Output = Chr(&H85) For i = 0 To 15 SetVolt (i) Next End Sub Private Sub BreakConnect() On Error Resume Next MSComm1.PortOpen = False Connect.Caption = "Co&nnect" End Sub Private Sub Combo1_Click() BreakConnect MSComm1.CommPort = Combo1.ItemData(Combo1.ListIndex) End Sub Private Sub Command1_Click() Debug.Print MSComm1.CommPort; ", "; MSComm1.Settings End Sub Private Sub Connect_Click() If Connect.Caption = "Co&nnect" Then MakeConnect Else BreakConnect End If End Sub Private Sub Form_Load() 'Dim i As Integer 'Dim v As Integer 'v = &H21 'For i = 0 To 15 'SX28Cmd(i) = v 'v = v + 2 'Next End SubThanks,
Kevin
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (DigitalDj) : 3/17/2008 10:59:30 PM GMT
You said, "I now know to send a string it is $FF for 255 and requires 3 bytes which is what I don't want to do, correct?"
Yes and no. Yes, you don't want to do this. No, $FF is not always a string for 255. In fact, it's not a string at all since it's not in quotes. Anything in quotes in a string. Here's a string:
"Kevin"
Here's another:
"$FF"
And here's a third:
"255"
If I write 255 and don't surround it with quotes, the VB compiler won't recognize it as a string.
$FF is just the hexadecimal version of 255 which is the decimal version of the binary 11111111.
Your program does send the correct values, but it seems you may yet not be clear on why. You have the line:
This line is taking the string variable called os$ and filling it with binary values by using the chr$ command. Here's a webpage that helps explain strings and the chr$ command:
www.vbexplorer.com/VBExplorer/focus/strings_tutorial.asp
Thanks,
PeterM