Flowing LEDs on a stairway ..better idea?

lbenson

Senior Member
I agree that ExpressPCB is a good bit easier to use than Eagle, and fairly easy to make new parts, but I don't find it inexpensive--at least relative to Oshpark.
 

newplumber

Senior Member
@ allycat okay I think I changed my schematic to what you mentioned I did add a coil but didn't know the symbol for the core and also where to put the coil? I figured since
it is protecting the 40x2 from noise so I tried to put it as close to it and thanks alot

@lbenson yes i could go down to a 20x2 lol all those wasted pins! and thanks

@ anyone If I used a 40x2 or 28x2 with a 10 mhz res would it be faster then a 20x2 with setfreq m64 ? Probably a forum here in details about it but just a quick question

@ Rq3 Your right about my resistors so I changed it to how the PE manual shows do I understand why? NO :) thats why I pat the person on the back who made up the manual
so I can follow the plan but when you mentioned about hard to find 20 k resistor? I don't know what is standard or none standard but i got spoiled and bought
a ton (well maybe 4 pounds) of resistor organizers from a auction and I can pretty much grab any resistor I want..which saves me so much time all labeled/organized
and thanks for pointing that out

On another note I only showed the leds in a reel for information only ..if you/anyone was to test this led strip while on a tight plastic reel ..it may melt the reel or something worse if left for a longer period of time
thats what happened to one my reels which was not a apa102 led strip type but was a 12 volt RGB 5m strip with a remote and all on full brightness ( I forget the name )


Now hopefully I am 99% schematic will work ok
Thanks again
 

Attachments

Last edited:

lbenson

Senior Member
... hard to find 20 k resistor
The E12 resistor series (10% tolerance) has values of 1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2 and 10.0 times a power of ten. Each number is chosen so that 10% high on the lower nominal value is about equal to 10% low on the next nominal value).

So in addition to 1R-10R in that sequence (proportion), you have 10R-100R; 100R, 120R, 150R, 180R, etc. up to 1K; 1K-10K (including the 4.7K commonly used as an I2C pullup); 10K-100K (including the 22K used as part of the PICAXE programming circuit), and so on.

If that makes sense.
 

newplumber

Senior Member
thanks lbenson learn something new everyday... well I have alot of none standard then along with standard but that is good to know
BTW lol sorry about missing your question about 8 or 16 sensors ...I am only planning on using 8 now but I am still out of town but when i get back
I will test them and see if myself can make it work ... I ordered like 30 of them just in case my testing takes a few mishaps
 
Last edited:

hippy

Technical Support
Staff member
A 20X2 is likely easier to use than a 28X2 or 40X2. I don't think a PCB is needed. It should be fairly easy to build it on strip-board. It doesn't seem it has to be small if using a PC power supply.
 

newplumber

Senior Member
thanks lbenson and hippy
I voted and I am going with 20x2 chip (voting results = ... me = 1,myself = 1, 40X2 = floating)
One thing I like about the 20x2 is the pins are the same with the 20m2 except with a lot more control like hspi etc
so its very easy for me use a 20x2 and since I will only be building one board, I will use a blank proto type one
but lbenson someday I will use your files when I understand eagle a little... always nice to have another tool

your friend mark (that charges by the hour and works very very slow)
 

lbenson

Senior Member
Mark--the 20x2 is indeed easy to work with--similarity to 20M2, 14M2, and 08M2 help.

No need to know Eagle to have the 20, 14, and 08 boards in that thread made by oshpark. You can just strip the ".zip" part of the names from the .brd file, and upload the file.
 

newplumber

Senior Member
okay Lance I will try that and I still am going to try learning eagle because you said I shouldn't ...JK no for reals I want to see if I can
catch on to some of it ... but thanks and for 20 bucks? I can't go wrong! .... or....ah....if it does go wrong it would be the same as
paying health insurance for 55 minutes (joking of course).


It doesn't seem it has to be small if using a PC power supply.
from hippy


If I was into computer design all of the laptops would be the size of the older diesel fueled furnaces where in north america
they built the house around them .. and your right I am not worried about space because 99% of the work is already in the 20x2
which is what? 1/4" X 1.00 " +/- so the box I plan on holding all this in is a jumbo desk top pc for the other 1% and plus so its
"no need magnification friendly" :)
 
Last edited:

newplumber

Senior Member
@ lbenson okay I ordered 3 boards for almost free thats awesome ... pretty easy instructions
so to get it right ..... I somehow get eagle to be my friend
then add file on oshpark like the one you've done and bingo get the board for my picaxe chip project (almost to easy)
btw way looks like you put sometime into that board and thanks
the file 20sip.sch wouldn't work but .brd did ..FYI
 

lbenson

Senior Member
the file 20sip.sch wouldn't work but .brd did ..FYI
Not sure if you're saying that the .sch file didn't work when sent to oshpark, or didn't work when loaded into Eagle. If the former, that's as expected--they take .brd files (because the schematic file doesn't tell them anything about the physical placement of the components and their connections). If it won't load into Eagle, I'll look into the problem.

Hope it works out for you. I didn't say you shouldn't try Eagle (jk or no jk), just that it is un-Windows-like in frustrating ways which seem unnecessary. Other PCB programs are easier (ExpressPCB is one), but at least for U.S. users, aren't as inexpensive or as convenient as Oshpark for small quantities with no great urgency.

Yes, that's right about Eagle and Oshpark. When you complete your board layout, you just upload the .brd file to Oshpark--no need to produce Gerber files (which is not hard to do with Eagle or most other PCB design programs).

Lance
 
Last edited:

newplumber

Senior Member
Yes lance I was meaning it wouldn't work for oshpark and you explained why and I know you never told me not to use Eagle ..some/to many times I think out loud
but thanks again for doing the hard work.
 

lbenson

Senior Member
I didn't list bill of materials for pcb:

20-pin dip ic socket: digikey AE9998-ND
CAP ALUM 10UF 20% 10V RADIAL: digikey 493-15985-ND
CAP CER 0.1UF 50V X7R RADIAL: digikey BC2665CT-ND
Resistor 22K
Resistor 10K

Headers: Depending on intended use, I use standard SIP headers for breadboard insertion, right angle SIP headers for Dupont wire connections, Long headers (1.27 or 1.4cm) for both breadboard and Dupont wire (at the same time), SIP female straight or right angle headers.

I use 1/6W or 1/8W resistors, and the holes on the pcb are sized for those. 1/4W resistors can be inserted almost vertical.

Dupont wires are very useful for quick rigging (for instance--various lengths are available):
http://www.ebay.com/itm/40pcs-Dupont-Wire-Color-Jumper-Cable-2-54mm-1P-1P-Female-Female-For-Arduino-/191674518846?hash=item2ca0b10d3e:g:X78AAOSwEeFVA-sE


Don't know if you have soldering equipment for PCBs. Most here would recommend an adjustable iron, but I've soldered many PCBs with this cheap Radio Shack 15-watter:

https://www.radioshack.com/products/15-watt-soldering-iron

The tips are very long-lived relative to the previous RS generation, but since RS is going out of business, you might want to order extras if you order this iron.

A near-lifetime supply of suitably thin 60/40 solder is here:

https://www.radioshack.com/products/rosin-core-solder-8-0-oz-1

You may know all of this, but lead-free solder is hard for hobby work, but 60/40 works well. Solder or flux used for plumbing is not to be used on electronics--acids will eat away connections in time.

Lance
 

newplumber

Senior Member
thanks Lance yes i know alot of things you mentioned but its good to know in case someone doesn't know or i forget.
I agree 100% about lead free solder even in plumbing it totally is a challenge (not the kind i like) ... I have a few good irons, my favorite soldering iron (weller WES51 with a sharp cone tip)
About the radio shack soldering iron? I guess i had very bad luck with it .. I think a 20ma led would get hotter (I probably didn't have it plugged in) but its been 10+ years since using a RS one
but your right for the price and if a person needs a solder iron then its probably the way to go. I personally believe why RS is going out of business is because they stopped shelving good IC parts.
All the materials you mentioned I think I have most of them .... I like how you suggest digikey numbers, they do have great parts
and I try to always use a IC socket but not so much if the picaxe goes bad (which i never had it happen) but to reuse it after all the china stuff goes bad.
I tried many rosin core solders but the best I found for me is radio shacks 62/36/2 rosin core solder .022" diameter
shown here and of course my luck they are sold out lol but I have enough rolls left for 3 oshpark boards I hope :)
https://www.radioshack.com/products/silver-bearing-solder
your friend mark
 

lbenson

Senior Member
The tips on the Radio Shack soldering irons of 10 years ago eroded quickly. The one I got 2+ years ago shows no sign of erosion. Yes, too bad about Radio Shack. Where would one go now locally to get a roll of solder or a capacitor or a resistor in time of need?

Except for a few "dead bug" instances in a tight spot, I always use a socket, and have never noted a failure, even with bought-in-bulk from ebay. I do use Digikey a lot, especially since they opened a Canadian online store. Jameco is another good U.S. source, though less likely to carry obscure parts.
 

newplumber

Senior Member
Okay here is another update
My led strips have finally came in but I ordered just white led strips so they are APA102 with single white led (not RGB) 30 per meter so total of 150
I was excited to see if I could get them to be my friend but failed for the first 2 days (which is okay...i was expecting 5)
here is my code and its from different parts of this form thanks to edmunds/westaust55/others but I always used PE5 and finally figured out I needed to use
PE6 for this code to work ... sorry I'm a little slow
Okay here is my problem .... #macro is something new for me to learn and I'm slowly grabbing on to some of it.
Here is my code
Code:
#picaxe 20X2 ' I am using 20x2 and have the hspi clk/hspi sdo  connected correctly 
#no_table
#no_data
setfreq m16

Symbol HOW_MANY_LEDS = 150

Symbol HOW_MANY_LEDS_MINUS_1 = HOW_MANY_LEDS - 1

; Set the brightness of the LED while testing
; Use small values to keep current consumption low
Symbol BRIGHTNESS    = 5 ; 0 to 255 (full)

; Initialise the HSPI interface
#macro init()
  hspisetup spimode00, spifast
#endmacro

; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

; Send the start of data header
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro

; Send a LED controlling command
#macro send( red, green, blue)
  sendPacket( $FF, blue, green, red )
#endmacro

; Send the end of data tail
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
#endmacro

PowerOnReset:

  ; Initialise the HSPI interface
  init

  ; Turn all LED modules off
  head
  for w0 = 1 To HOW_MANY_LEDS
    send( $00, $00, $00 ) ; 1 to last = Off
  next
  tail

BounceLed:
  ; Set one LED at a time
  ; 'w0' indicates which LED to set
  do
  head
        
    for w0 = 1 to HOW_MANY_LEDS
    send( BRIGHTNESS, $00, $00 ) ; red
     pause 10
    next
tail
    for w0 = HOW_MANY_LEDS_MINUS_1 to 1 step -1
      Gosub SetLed
    next
  loop

SetLed:
  ; Set a specific LED and keep the others off
  head
  for w1 = 1 to HOW_MANY_LEDS
            if w1<w0 then send( BRIGHTNESS, $00, $00 ) ; red
 elseif w0<HOW_MANY_LEDS then send( $00, $00, $00 ) ; red
 endif
  next
  tail
  return
My problem is if I run this code it turns all the leds on and then slowly turns one off at a time which I think is supposed to do that.
But since I can not figure this #macro and heads/tails I can not custom make it do what i want it to do
So (sorry for the blah blah) but I want it to start at the first led and run to the last with only one being on at a time
Is it possible I can have a code with out #macro and heads/tails or that is to much? If so I will keep reading ....I probably am thinking to deep again
And of course all you cool friends have helped me way to much already
I added a picture of my test board that doesn't have the APA102 in it ...and its junk pine wood that's all twisted and stuff lol but it works for a test
Your very slow picaxe learning friend mark
 

Attachments

Last edited:

techElder

Well-known member
newplumber, #macro is a way to provide different parameters to a command with the same code.

When PE6 puts your code together for downloading to the PICAXE it inserts the #macro code with the provided parameters into your code.

So, every time you call the macro code name, PE6 adds all the necessary code. You won't see that in your source, though.

Using the #macro method makes your source code easier to read.
 

newplumber

Senior Member
Thanks texas lol you have simple me trying to learn PE6 and spi and I think I can do it but it makes it just that much more of a challenge which is fun as long as I make progress
Okay so the source code is what i am missing here in the #macro so in example
Code:
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro
so when it run into
Code:
  head
        
    for w0 = 1 to HOW_MANY_LEDS
    send( BRIGHTNESS, $00, $00 ) ; red
     pause 10
    next
where/what does it do with sendpacket ( $00, $00, $00, $00 )

BTW after spending sometime on PE6 ... It is a fantastic editor ... I just have to delete PE5 in my head
 
Last edited:

hippy

Technical Support
Staff member
To get your LED's to light one at a time, untested -

Code:
PowerOnReset:

  ; Initialise the HSPI interface
  init

  ; Turn all LED modules off
  head
  for w0 = 1 To HOW_MANY_LEDS
    send( $00, $00, $00 ) ; 1 to last = Off
  next
  tail

  ; Set one LED at a time
  ; 'w0' indicates which LED to set
  do
    for w0 = HOW_MANY_LEDS_MINUS_1 to 1 step -1
      Gosub SetLed
    next
  loop

SetLed:
  ; Set a specific LED and keep the others off
  head
  for w1 = 1 to HOW_MANY_LEDS
     if w1 = w0 then 
       send( BRIGHTNESS, $00, $00 ) ; red
     else
       send( $00, $00, $00 ) ; off
     endif
  next
  tail
  return
Note the change for "w1<w0" to "w1=w0".
 

lbenson

Senior Member
where/what does it do with sendpacket ( $00, $00, $00, $00 )
Part of the confusion is that the code has macros (e.g., send()) using macros (sendPacket()). Nothing wrong with that--it's a good generalization of the code--but it makes it less immediately clear what is happening.

All a macro does is insert the code within the macro into your program, using your real variables/constants instead of the pseudo ones named in the macro definition.

So "send( BRIGHTNESS, $00, $00 )" becomes "sendPacket( $FF, BRIGHTNESS, $00, $00 )", but since "sendPacket" is another macro, it becomes "hspiout($FF, BRIGHTNESS, $00, $00)". This is the code that is actually executed.

Macros allow you to use the same code form over and over without actually typing it in, and also allows you to use different values when executing the macro code in different places.

Glad you've got a start on getting it working.

EDITED: In another post today, something I didn't know:
If one selects Options, Diagnostics and ticks the Pre-processor, 'Display pre-processor output' option one can see what the actual code generated will be when the code is Syntax Checked.
"Options" is the little wrench under "Workspace Explorer".
 
Last edited:

hippy

Technical Support
Staff member
Macros can be a bit of a double-edged sword; in making it easier to code what one wants, providing a means to specify actions without worrying how those actions are actually performed or initiated, it does to an extent hide what is actually going on.

For coding light control programs, it is only necessarily use the 'Init', "Head", "Send" and "Tail" macros.

Note that the "Send(r,g,b)" macro handles the reordering of how we like to specify colour (r,g,b) into the "$FF,$bb,$gg,$rr" sequence the hardware requires.

If one selects Options, Diagnostics and ticks the Pre-processor, 'Display pre-processor output' option one can see what the actual code generated will be when the code is Syntax Checked.
 

newplumber

Senior Member
@ lbenson thanks for the clearer picture I will need to test/retest and then once I have it ... I will understand a whole lot more of whats going on ...
but I think I'm on the right track...
"glad you got a start on it working" <---- if you only knew how many program tries it took to make one/some of the lights to turn on....you would be amazed and i wont say :)
but 550 of them was using PE5 (joking) but the connecting wires to strip was
red = data in
green = clk
blue = ground
black = +5 volt ( i am guessing someone is color blind putting these together) which is easy to figure out but why?
maybe someone like me is building these things up


@hippy thanks for the "untested code" but I tested it and like always it works awesome plus your helping quote that lbenson highlighted does just what i wanted to see
I just need a little more practice taking the #macro to fully understand it ... that's the best way i learn anyhow
so examples ,examples,examples is worth 1000 books and in this little simple code there is tons and thanks again


now back to PE6 (of course after I fix resistance in sewer lines)
 

hippy

Technical Support
Staff member
I just need a little more practice taking the #macro to fully understand it ... that's the best way i learn anyhow
That's probably the best way to learn. Once one is familiar with how it works it gets easier to follow how others are using them.

When looking at other people's code one problem is in not immediately understanding how something was put together, why it is how it is. In this case "send(r,g,b) may be obvious, creates the data to be what needs to go to the hardware, but why does that invoke "sendPacket" rather than output directly ?

The answer to that is it allows HSPIOUT to be changed to bit-banging code at a single point in the code, solely within the "sendPacket" macro, rather than having to change it in all the places where "sendPacket" is invoked within other macros.

So, during development, initial code which may be ...

Code:
#macro head()
  hspiout ( $00, $00, $00, $00 )
#endmacro
#macro tail()
  hspiout ( $FF, $FF, $FF, $FF )
#endmacro
evolved into ...

Code:
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
#endmacro
And now one can alter "sendPacket" without worrying about the rest of the code, knowing that as long as the new code in "sendPacket" works as required, so too will everything else, everything already using "head" and "tail" macros.
 

newplumber

Senior Member
Okay thanks hippy that explains where I became confused (sendpacket) and I am getting the macros down (still need a ways to go tho)
but if I am thinking right ...in a simple way
Code:
#macro tail()
  hspiout ( $FF, $FF, $FF, $FF )
#endmacro
so every where in the code that is printed ( tail ) its like gosub #macro tail()... but I'm guessing its faster and already has it in memory
so it doesn't jump but adds that part of code with out adding alot more bytes to the code?
And after using your trick on "actual code generated with Syntax Checked" saved me a lot more confusion
So here is my new code for my led strip
Code:
'This code is not perfect and is made possible only from help of picaxe forum 
;#picaxe 20x2 code uses picaxe 20X2 on single white APA102 led strip (not RGB)
#NO_TABLE ' it has 150 leds and turns one led on after another 
#NO_DATA  ' so example of 8 leds...10000000-11000000-11100000 etc
          ' then turns them off in the same way backwards
setfreq m64 '<--- m64 with spislow is faster then m32 with spifast for my code test

Symbol leds_on_or_off = b4
Symbol count1         = b5 

Symbol HOW_MANY_LEDS = 150
Symbol LEDS   =  HOW_MANY_LEDS
Symbol BRIGHTNESS    = 10 ; 0 to 255 (full)



START:
 hspisetup spimode00, spislow
    FOR b0 = 1 to HOW_MANY_LEDS  
         gosub flow_led
     NEXT b0 
       FOR b0 = HOW_MANY_LEDS to 1  step -1 
         gosub flow_led
     NEXT b0
        gosub LEDS_OFF
GOTO START

LEDS_OFF:
        hspiout( $00, $00, $00, $00 )
   FOR b0 = 1 To HOW_MANY_LEDS  ; 1 to last = Off
        hspiout( $FF, $00, $00, $00 )
   NEXT b0
       hspiout( $FF, $FF, $FF, $FF )
RETURN

FLOW_LED:; leds on + leds off needs to = total leds  
   hspiout( $00, $00, $00, $00 )
       FOR leds_on_or_off = 1 to b0
		hspiout( $FF, $00, $00, BRIGHTNESS )
       NEXT
count1 =   LEDS - b0
       FOR leds_on_or_off = 1 to count1
		hspiout( $FF, $00, $00, $00 )
       NEXT
    hspiout( $FF, $FF, $FF, $FF )
RETURN
When I ran this code I thought about using #macro but I needed more time and wanted to see the led strip work because its important :)
I am finally grabbing a hold of Hspi for 20x2 makes it easy with hspiout
but if a person runs this code the LEDS_OFF: ....sub will not clear the strip unless you add
gosub LEDS_OFF
gosub LEDS_OFF <--- twice which I don't understand why ...even when I run it on setfreq m16 and spislow or spifast
I will keep trying to find out why ....
Other then that it runs perfectly for a start ...hopefully it makes sense
 

hippy

Technical Support
Staff member
Yes; you will need to call LEDS_OFF to clear the LEDs. As to why you have to call it twice that may be because you are using more than 64 LEDs. I believe you need to have more "Tail()" sequences to clock data through the LED strip once over 64. As you have over 128 you may need to have three "Tail()" sequences to guarantee all LEDs are cleared.
 

lbenson

Senior Member
Glad you are making progress. Just a couple of notes of no functional consequence:

Regarding the stylistic matter of indentation of code, the purpose is to distinguish "blocks" of code--executable commands that fall in a sequence. A subroutine is an example of a syntactical "block", so typically the subroutine name has no indentation or one level. The code within the subroutine is indented another level (and may have further indentations for blocks within IF or FOR or SELECT statements to whatever level is needed). The "RETURN" is indented to the same level as the other code in the subroutine. Other end-of-block statements (ENDIF, NEXT) are indented the same as the beginning of the block (IF, FOR).

What is an indentation "level"? Well, many people use a tab, and some use 4 spaces. My personal preference after decades of programming is two space characters per level. The problem with tabs is that if you move them out of the environment in which they were entered, they may show differently than expected. Two spaces should look the same anywhere, and can handle a great many levels of blocks within blocks.

For instance, your START main block would look like this:
Code:
START:
  hspisetup spimode00, spislow
  FOR b0 = 1 to HOW_MANY_LEDS  
    gosub flow_led
  NEXT b0 
  FOR b0 = HOW_MANY_LEDS to 1  step -1 
    gosub flow_led
  NEXT b0
  gosub LEDS_OFF
  GOTO START
For me, because I am compulsive about avoiding GOTO, I would use a perpetual DO loop block:
Code:
START:
  hspisetup spimode00, spislow
  DO
    FOR b0 = 1 to HOW_MANY_LEDS  
      gosub flow_led
    NEXT b0 
    FOR b0 = HOW_MANY_LEDS to 1  step -1 
      gosub flow_led
    NEXT b0
    gosub LEDS_OFF
  LOOP
That is a matter of personal preference of no function consequence (in a program this small), but is considered "best practice". (Note that you don't need to repeat HSPISETUP at each pass through the loop.)

You may note that the difference between your ON and OFF commands is the last byte in the HSPIOUT command--either BRIGHTNESS or $00. You could generalize this code by defining a byte variable, (e.g., SYMBOL level=b6), and then call a single routine "hspiout( $FF, $00, $00, level )" after setting either "level=BRIGHTNESS" or "level=$00". (I don't have your LED strip, so I am speculating based on your code.)
 
Last edited:

hippy

Technical Support
Staff member
You may note that the difference between your ON and OFF commands is the last byte in the HSPIOUT command--either BRIGHTNESS or $00. You could generalize this code by defining a byte variable, (e.g., SYMBOL level=b6), and then call a single routine "hspiout( $FF, $00, $00, level )" after setting either "level=BRIGHTNESS" or "level=$00". (I don't have your LED strip, so I am speculating based on your code.)
Or, to build on the case with macros, the earlier suggestion of -

Code:
SetLed:
  ; Set a specific LED and keep the others off
  head
  for w1 = 1 to HOW_MANY_LEDS
     if w1 = w0 then 
       send( BRIGHTNESS, $00, $00 ) ; red
     else
       send( $00, $00, $00 ) ; off
     endif
  next
  tail
Could become -

Code:
#Macro ledOn()
       send( BRIGHTNESS, $00, $00 )
#EndMacro
#Macro ledOff()
       send( $00, $00, $00 )
#EndMacro

SetLed:
  ; Set a specific LED and keep the others off
  head
  for w1 = 1 to HOW_MANY_LEDS
     if w1 = w0 then 
       ledOn
     else
       ledOff
     endif
  next
  tail
The core principle of macros is to build foundation blocks which can then be easily used elsewhere. Once one has figured out how to turn a LED on or off it's not necessary to do that everywhere one needs that, only to use the macro name which will ensure that gets done.

The advantage is that for the second code, it's clear for others reading that what is happening within the SETLED routine without having to understand what is being done or even having to look at how it is being done.
 

newplumber

Senior Member
@ hippy Thanks ..so if a person had 60 per meter led strip and had 5 meter strip they should use "gosub leds_off" 5 times ... makes sense
I also did not know 20X2 has a spislow or spimedium or spifast so after I used setfreq m64 and spimedium I am really impressed of the speed
maybe it can create problems but so far its been working great...If I use setfreq m64 and spifast ....the led strip goes berserk
EDIT > I will look at your last post and try to make it clear thanks again


@lbenson thanks for all the pointers and I will try start using DO...loop which does make sense and I can see see why your "compulsive about avoiding GOTO"
I guess I learned all my programming from picaxe help/ forums and I have "just" a little ways to go to catch up to you :) "in decades of programming" ..I only need another 81,000 hrs
I always try to code like
BLOCK:
....DO ------- have to use "......" other wise its not tabbed right in this forum box
.......code
..........code
.......code
...LOOP until code
RETURN

but looking at your way

BLOCK:
..DO
...code
...code
...code
..LOOP until code
RETURN

I will try code like that and i know like you said everyone has personal preference but if we all code the same
it makes it easier for you/others to figure out where my code goes delusional

Its good you give pointers because I never see your side of how you look at inexperienced programmers like me
I know I don't need to repeat HSPISETUP but I was trying to see if my gosub LEDS_off would work with it every time and forgot to paste it back above start
but hippy explained it clearly how to fix it.

So now that I have 80% of my code fixed
Hopefully this weekend I can get this project wrapped up (might take a few sicks days from work...or I could just fire myself)

mark
 
Last edited:

hippy

Technical Support
Staff member
@ hippy Thanks ..so if a person had 60 per meter led strip and had 5 meter strip they should use "gosub leds_off" 5 times ... makes sense
Sort of, but not quite. Each HSPIOUT pushes LED data up the chain and the "tail()" function pushes things further along, and how far along it is pushed depends on the number of four $FF bytes are sent in that "tail()".

What one should do is increase the number of $FF bytes sent in the "tail()" function to match the number of LEDs used.

Calling "leds_off" multiple times might work because it's also pushing things up the strip, but if one watched closely, it would clear the first set, re-clear the first set while clearing the next set as a by-product of that, etc.

It's a bit complicated because what comes out of each LED module is delayed in comparison to what goes in; more clock pulses are needed than data bits and those "tail()" bytes are dummy data bytes just to provide the additional clock pulses. I'll admit I can't remember the exact details better than that.

Perhaps think of it like kicking a number of balls into another ball to move that along, where the proper way to do it would be to kick the first ball harder, send more $FF bytes in "tail()".

If I use setfreq m64 and spifast ....the led strip goes berserk
Could be that this gives an SPI speed which is just too high for the LED strip to handle. I haven't looked in the datasheet to check.
 
Last edited:

newplumber

Senior Member
Hippy I really like your kicking the ball example makes it simple and I suppose you mean send more $FF bytes in "tail" or just meaning more bytes in general and i understand

Code:
#picaxe 20x2 'One step closer to final code 
#no_table
#no_data
Setfreq m64
Symbol loopA         = b1
Symbol loop1         = b2
Symbol count1        = b3
Symbol ptime         = 20000
Symbol HOW_MANY_LEDS = 151
Symbol LEDS = HOW_MANY_LEDS
Symbol BRIGHTNESS    = 10 ; 0 to 255 (full)
'setup
#macro init()
  hspisetup spimode00, spimedium
#endmacro
; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

#macro send( NOled, NOled1, white)
  sendPacket( $FF, NOled, NOled1, white )
#endmacro
; Send the start of data tail
#macro head()
  sendpacket($00, $00, $00, $00)
#endmacro
; Send the end of data tail
#macro tail()
  sendpacket($FF, $FF, $FF, $FF)
#endmacro
' turn on a led
#Macro ledOn()
  send( $00, $00, brightness)
#EndMacro
' turn off a led
#Macro ledOff()
  send( $00, $00, $00)
#EndMacro

START:
 init
 FOR b4 = 0 to 2 ' KICK THE BALL VERY HARD 3 times :)
  head
  For loopA = 1 to HOW_MANY_LEDS 
   ledOff 
  Next
  tail 
  pause 10
 NEXT b4
DO
  gosub SCROLL_FIRST_LEDS_ON :pause ptime' turns leds ON  1st..2nd..3rd...
  gosub SCROLL_FIRST_LEDS_OFF:pause ptime' turns leds OFF 1st..2nd..3rd...
  gosub SCROLL_LAST_LEDS_ON  :pause ptime' turns leds ON  150th..149th..148th...
  gosub SCROLL_LAST_LEDS_OFF :pause ptime' turns leds OFF 150th..149th..148th...
LOOP	
 SCROLL_FIRST_LEDS_ON:
  For loopA = 1 to HOW_MANY_LEDS : b0 = loopA 
   head
    FOR loop1 = 1 to b0
     ledOn
    NEXT loop1
  count1 = LEDS - b0
    FOR loop1 = 1 to count1
     ledOff
    NEXT loop1
   tail
  NEXT loopA
 RETURN 
   
 SCROLL_FIRST_LEDS_OFF:  
  For loopA = 1 to HOW_MANY_LEDS : b0 = loopA  
   head
    FOR loop1 = 1 to b0
     ledOff
    NEXT
  count1 = LEDS - b0 
    FOR loop1 = 1 to count1
     ledOn
    NEXT
   tail
  NEXT loopA
 RETURN

 SCROLL_LAST_LEDS_ON:
 For loopA = HOW_MANY_LEDS to 0 step -1 : b0 = loopA 
   head
    FOR loop1 = b0 to 1 step -1
     ledOff
    NEXT loop1
  count1 = LEDS - b0
    FOR loop1 = count1 to 0 step -1
     ledOn
    NEXT loop1
   tail
  NEXT loopA : gosub ADD_BTYE
 RETURN

SCROLL_LAST_LEDS_OFF:  
For loopA = HOW_MANY_LEDS to 0 step -1 : b0 = loopA  
  head
   FOR loop1 = b0 to 1 step -1
    ledOn
   NEXT
count1 = LEDS - b0 
   FOR loop1 = 0 to count1
    ledOff
   NEXT
  tail
 NEXT loopA : gosub DEC_BTYE
RETURN

 ADD_BTYE: 'makes so all leds are on ...if I dont use this gosub then last led don't light
  FOR b4 = 0 to 2  
   head
   For loop1 = 1 to HOW_MANY_LEDS 
    ledOn 
   Next
   tail 
   pause 10
  NEXT b4
 RETURN
 DEC_BTYE: 
  FOR b4 = 0 to 2 'makes all the leds turn off...if I dont use this gosub then last led stays lit 
   head
   For loop1 = 1 to HOW_MANY_LEDS 
    ledOff 
   Next
   tail 
   pause 10
  NEXT b4
 RETURN
I know most of this code is borrowed but I am understanding more
what i don't understand is
Code:
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro
n1,n2...? I read the awesome pdf switching PE5 to PE6 and I guess i am missing something
Although this code works so far for my application and I know it can be shorter but I tried to use
#macro where I could and takes 365 bytes
I do love the simulator and tried to figure out a better way then to use "gosub ADD_BYTE"
and lance I tried to code like a rookiepro but i am probably way off , but absolutely NO GOTO's
Now that I used alot of #macro it sure was easily to code (of course I didn't make any #macros by myself)
but someday I think I can.
 

hippy

Technical Support
Staff member
Hippy I really like your kicking the ball example makes it simple and I suppose you mean send more $FF bytes in "tail" or just meaning more bytes in general and i understand
Yes, $FF bytes in tail() not $00 bytes. I have corrected the earlier post. What you want is something like ...

Code:
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF )
  sendPacket( $FF, $FF, $FF, $FF )
  sendPacket( $FF, $FF, $FF, $FF )
#endmacro
what i don't understand is
Code:
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro
n1,n2...?
Those are just arbitrary parameter names as with other macros.
 

lbenson

Senior Member
Code:
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro
n1,n2...?
Those are just arbitrary parameter names as with other macros.
To elaborate further, n1, etc. are like placeholders, which are replaced by your real parameters when the macro code is expanded and executed.

For example, "tail" expands to "sendpacket($FF, $FF, $FF, $FF)"; "sendpacket" is another macro, and in it's expansion, the "n1", "n2" placeholder parameter names are replaced by the "$FF" values, so the "tail" is completely expanded to "hspiout ($FF, $FF, $FF, $FF)".
 

hippy

Technical Support
Staff member
This is the code I would start with when using more than 64 LEDs. It turns them all on for 2 seconds then all off for 2 seconds. First check is that it is doing that; that all are on and all are off when they are meant to be.

Code:
#picaxe 20x2
#no_table
#no_data

; Set how many LED modules in the strip
symbol HOW_MANY_LEDS = 151

; Set the brightness of the LED while testing
; Use small values to keep current consumption low
symbol BRIGHTNESS    = 1 ; 0 to 255 (full)

; Initialise the HSPI interface
#macro init()
  hspisetup spimode00, spifast
#endmacro

; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

; Send the start of data header
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro

; Send a LED controlling command
#macro send( red, green, blue)
  sendPacket( $FF, blue, green, red )
#endmacro

; Send the end of data tail
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF ) ; 1-64
  sendPacket( $FF, $FF, $FF, $FF ) ; 65-128
  sendPacket( $FF, $FF, $FF, $FF ) ; 129-192
#endmacro

; Turn a single LED off
#macro ledOff
  send( $00, $00, $00 )
#endmacro

; Turn a single LED on
#macro ledOn
  send( BRIGHTNESS, $00, $00 )
#endmacro

PowerOnReset:

  ; Initialise the HSPI interface
  init

  do
    gosub AllOff ; Turn all LEDs off
    pause 2000
    gosub AllOn  ; Turn all LEDs on
    pause 2000
  loop

AllOff:
  head
  for w0 = 1 to HOW_MANY_LEDS
    ledOff
  next
  tail
  return

AllOn:
  head
  for w0 = 1 to HOW_MANY_LEDS
    ledOn
  next
  tail
  return
Set the HOW_MANY_LEDS symbol to how many LEDs you actually have. I wasn't sure if it is 151 or 150 and you'd adjusted that to make things work.

I also reduced the BRIGHTNESS symbol to its lowest value.
 

newplumber

Senior Member
Thanks Lance

so how does it change "n1" into "$ff" ... probably real simple, but probably thinking to deep again
So
#macro sendPacket( n1, n2, n3, n4 ) <--- so reserves 4 bytes of memory?
hspiout( n1, n2, n3, n4 ) <---tells to hspiout the 4 bytes of memory?
#endmacro

#macro head()
sendPacket( $00, $00, $00, $00 ) <--- puts $00 into the reserve byte of n1,n2 etc?
#endmacro

So when "head" is programmed
goes to/automatically puts $00 into n1,n2....
then goes to/automatically hspiout's the 4 bytes?
I guess I have to understand it like gosubs where it jumps to someplace ...even if it don't

@ hippy yes I have 150 leds but I rigger jigged it so it will work with 151 other wise the last led does not light with
Code:
gosub SCROLL_FIRST_LEDS_ON :pause ptime' turns leds ON  1st..2nd..3rd...
I tried your code and all leds are working on/off
but when I change the pause to this
Code:
 do
    gosub AllOff ; Turn all LEDs off
    pause 20000 '2000
the led strip just stays on with out turning off ..on lowest setting
I added longer pause just so i can make sure the off is working
 

newplumber

Senior Member
I also tried
Code:
  do
    gosub AllOff ; Turn all LEDs off
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
    pause 2000
still all on

and if I try this
Code:
    gosub AllOff ; Turn all LEDs off
    pause 2000   
    gosub AllOn  ; Turn all LEDs on
    pause 20000
the leds stay off
 

hippy

Technical Support
Staff member
so how does it change "n1" into "$ff" ... probably real simple, but probably thinking to deep again
It's really just substitution ...

Code:
#Macro Hello( whoever )
  SerTxd( "Hello ", whoever, CR, LF )
#EndMacro

Hello( "Tom" )
Hello( "Dick" )
Hello( "Harry" )
The 'whoever' doesn't do anything other than convey what you use in the macro invocation ( "Tom", "Dick" or "Harry" ) into the desired position in the SERTXD.

SERTXD(whoever) becomes SERTXD("Tom"), SERTXD("Dick"), and SERTXD("Harry").

yes I have 150 leds but I rigger jigged it so it will work with 151 other wise the last led does not light
It is best to set the symbol to the number of LEDs you actually have. If that doesn't work then fix it how it should be fixed because bodging it to work can have other undesirable knock-on effects. Maybe not in this case, but bodging things to work is not a good habit to get into.

when I change the pause to this ... the led strip just stays on with out turning off
Not sure what is going on there, why things are not working with longer pauses. Is your code exactly as was posted and only the PAUSE length changed or have you altered anything else ? If you have it's best to post all your code.

Added: It would be best to get what I posted working before anything else. With HOW_MANY_LEDS set to the actual number you have connected, does that turn on and off all LEDs ?
 
Last edited:

newplumber

Senior Member
thanks hippy yes my code is exactly like the one you posted
the only thing changed is the pauses
but my other codes i used when i added a pause it seemed to ignore it and jump to the next line
but I don't want to waste your time, it just something to mention and I can get around it for now
btw I wont get into "bodging" lol and understand exactly what problems they can cause.
My code for this project works perfectly well and been running for 12 hrs flawlessly.
I can see if i wanted to add more bells and whistles later on then I would have to crunch down more perfectly
but its stairs and I will make it simple because if my code goes berserk it's not like the stairs do too

It's really just substitution
okay I was thinking to deep..have to get it simple
again thanks for the tons of help.

EDIT> when I made
Symbol pause_word = W1
pause_word = 20000

it then works flawlessly just a note

so your code with added pause_word
Code:
#picaxe 20x2
#no_table
#no_data

Symbol PAUSE_WORD = W1
PAUSE_WORD = 20000
; Set how many LED modules in the strip
symbol HOW_MANY_LEDS = 151

; Set the brightness of the LED while testing
; Use small values to keep current consumption low
symbol BRIGHTNESS    = 1 ; 0 to 255 (full)

; Initialise the HSPI interface
#macro init()
  hspisetup spimode00, spifast
#endmacro

; Send a four byte packet out via HSPI
#macro sendPacket( n1, n2, n3, n4 )
  hspiout( n1, n2, n3, n4 )
#endmacro

; Send the start of data header
#macro head()
  sendPacket( $00, $00, $00, $00 )
#endmacro

; Send a LED controlling command
#macro send( red, green, blue)
  sendPacket( $FF, blue, green, red )
#endmacro

; Send the end of data tail
#macro tail()
  sendPacket( $FF, $FF, $FF, $FF ) ; 1-64
  sendPacket( $FF, $FF, $FF, $FF ) ; 65-128
  sendPacket( $FF, $FF, $FF, $FF ) ; 129-192
#endmacro

; Turn a single LED off
#macro ledOff
  send( $00, $00, $00 )
#endmacro

; Turn a single LED on
#macro ledOn
  send( BRIGHTNESS, $00, $00 )
#endmacro

PowerOnReset:

  ; Initialise the HSPI interface
  init

  do
    gosub AllOff ; Turn all LEDs off
    pause PAUSE_WORD
    gosub AllOn  ; Turn all LEDs on
    pause 2000
  loop

AllOff:
  head
  for w0 = 1 to HOW_MANY_LEDS
    ledOff
  next
  tail
  return

AllOn:
  head
  for w0 = 1 to HOW_MANY_LEDS
    ledOn
  next
  tail
  return
 
Last edited:
Top