Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
version0.5
JasStrong<jasmine@heroicrobotics.com>
0. Introduction
ThePixelPusherisasimplebeast.Ittakespixelsfromthenetwork,anditpushesthemoutto
intelligentLEDsasfastasitcan.IthassomesoftwareinsideitthatrunsasimpleTCP/IP
networkstack,andanumberofmodulesthattellithowtotalktodifferentLEDcontrolchips.
Thesophisticationinthissystemcomesfromthedesignofthenetwork.PixelPusheris
designedtobeplugandplaytoabstractthecomplexityofthetaskawayfromtheuserto
allowartistsandarchitectstoconcentrateontheinterestingpartofthedesignequation.
Weprovideasoftwarestackthatiscomprisedofthreecomponents:
1.Firmware
Thefirmwareisapieceofsoftwarethatisloadedintotheflashmemoryofthe
PixelPushercontrollercards.Itcontainsabout100kilobytesofmachinecode.Itcontainsa
realtimeoperatingsystem,anetworkstack,aFATfilesystem,aUSBstack,andasignalling
stacktotalktothestripsorpixelsyouhaveattached.
2.Thelibrary
ThelibraryisapieceofJavacodewhichrunsonthecontrollingcomputer.Itconsistsof
asetofclasseswhichcollectivelyfind,makeorderly,andtalktooneormorePixelPusher
controllers.
3.Examples
Theexamplesareprovidedinthelibrarypackage.Theyaregenerallyquitesimple
implementationsoftherequiredsoftwaretomakeaPixelPusherarraywork.Ifyouhaveinstalled
thelibrary,youcanfindtheminProcessingsExamples...dialogue,underContributed
Libraries.
1. To begin...
1. Thefirstthingyoullneedisacomputer.ThesoftwareisbasedonProcessing,sohead
tohttp://processing.org/andpickuptherightversionforyourmachine.Itisavailablefor
PC,MacandLinux,soyoushouldbeprettywellcovered.
2. Nextyouneedtoinstallthelibrary.Youcanfindinstructionsonhowtoinstalllibraries
intoProcessingathttp://wiki.processing.org/w/How_to_Install_a_Contributed_Library
notethatatthetimeofwriting,PixelPusherisnotyetincludedintheAddlibrary...tool,
soyouwillhavetodoitmanually.YoucanfindthePixelPusherlibraryat
http://forum.heroicrobotics.com/notethatitisfrequentlyupdated,sobesuretokeepup
todate.
3. Thirdly,youshouldupdatethefirmwareonyourPixelPusher.Itisquitelikelythatnew
firmwareversionshavecomeoutsinceyourproductshipped,aswefollowacontinuous
developmentmethodology.Dontworryitsquiteeasytodo,andallyouneedisamini
USBcable.YoucanfindinstructionsonhowtodothisintheHowToPushPixels
document,alsoavailablefromtheHeroicRoboticsforum.
4. Andlastly,youwillneedtowriteaconfigurationfileforeachPixelPusherinyoursystem,
saveeachoneontoaUSBmemorystick,andinsertitintotheappropriatePixelPushers
USBhostport.Then,tomakethemreadtheirconfiguration,presstheresetbuttonor
powerthePixelPusheroffandthenon.Theconfigurationfileis,again,explainedinthe
HowToPushPixelsdocument.
YoullneedtoconnectallthePixelPusherstothesamenetworkyourcomputerison,ofcourse.
Onceyouvedonethat,youcanopenoneofthePixelPusherexamplesinProcessing,hitrun
andyoushouldseeitpickupallyourPixelPushersinafewseconds.
PixelPusherisdesignedtoautomaticallyconfigurethearray,anditdoesthisusingtwotypesof
message.OneissentfromacontrollingcomputertothePixelPushers,andtheotherissent
fromthePixelPusherstothecontrollingcomputer.Skipthenextpageifyourenotcuriousabout
howthisworks.
A technical aside:
ThemessagesthataresentfromthePixelPushertothecontrollingcomputerfollowaformatwecallthe
UniversalDiscoveryProtocol.ThesepacketsaresentonceasecondbyallthePixelPushersonthe
network.TheycontainseveralpiecesofinformationaboutthePixelPusher,andarepickedupandstoredin
adatabasebythelibrary.Thepiecesofinformationinclude:
thePixelPushersIPaddressandMACaddress
twonumberscalledthegroupordinalandcontrollerordinal,assignedbytheuser
howmanystripsareattachedtothisPixelPusher
howmanypixelsareineachstrip
howlongittakesthisPixelPushertoprocesseachpacketofdata
howmanypacketsthePixelPushermissedinthelastsecond
howmanystripscanfitintoasingledatagram(packet).
aflagbyteforeachstrip,describingthepixellayout(RGBorRGBOW,24bitor48bit,
renormalizedorlinear).
thesoftwareversionthePixelPusherisrunning
aflagwordforthePixelPusher,denotingwhetheritrequirespackedstripdatagrams
Thelibraryusesthisinformationtobuildarepresentationofthearrayinmemory.This
representationispopulatedwithPixelPushersastheyareseen,andkeptuptodateasdiscovery
packetsarrive.Theapplicationsoftwarecanthenaskthelibraryforpiecesofthis
representation,andmodifythepixelsinthemodelthelibraryhandlessendingupdatesoutto
thePixelPushersautomaticallyandasynchronously.Todothis,itusesthesecondformof
traffic.
Stripupdatesarepackedintodatagramsandsentbythisprotocol.Thepacketcontains
informationrelatingtospecificstrips,including:
apercardsequencenumberforthecurrentpacket
astripnumberfromzerotoseven
anumberofRGBtripletsappropriatetothenumberofpixelsinastrip
SincethememoryavailabletotheethernetcontrolleronPixelPusherislimited,onlyalimited
numberofpixelscanbesentinasingledatagram.Withourusualmaximumof240pixelsper
strip,twostripscanbesentineachdatagram.Eachdatagramhasasinglesequencenumber,
followedbyavariablenumberofrepetitionsofthestripnumberfollowedbythepixeldata.The
timinginformationandthemissedpacketdatafromthediscoverypacketareusedtothrottlethe
packetsbeingsenttotheavailablesystembandwidth.
WeanticipatethatyoumightwanttohavemorethanonesectiontoyourPixelPusherarray.
Maybeyourelightingdifferentareas,oryouwanttohaveabigbillboardsizedvideodisplaythats
separatefromyour3dsculpture.Thatswhyweimplementedgroupsandcontrollers.
WhenthelibraryenumeratesaPixelPusheritreadsfromittwonumbers,whicharecalledgroup
andcontroller.Eachgroupisacollectionofcontrollers,andwithineachgrouptheyareordered
bythecontrollernumber.Youcanselectcontrollersbygroup,oryoucanjustselectallofthem
atonce,inwhichcasetheyareorderedfirstbygroupandthenbycontrollerso,forexample,
group2controller1comesbeforegroup2controller2,butgroup1controller37comesbefore
either.Iftwocontrollershavethesamenumber,theethernethardwareaddressisusedasa
tiebreaker.Sothereisathreelevelhierarchy:
Asyoullseefromourexamples,thereareafewbitsandpiecesyoullneedinyourProcessing
sketchinordertomakethesystemwork.Heresaquickrundown.
Theimports
PixelPusherdefinesanumberofclassesthatprovideessentialfeatures.Atthetopofthesketch
youllseeablockthatlookslikethis:
importcom.heroicrobot.dropbit.registry.*
importcom.heroicrobot.dropbit.devices.pixelpusher.Pixel
importcom.heroicrobot.dropbit.devices.pixelpusher.Strip
importjava.util.*
Thisimportstheregistry,whichisthesoftwarecomponentthatlistensforthediscoverypackets,
thePixelPusherabstractionsforPixelsandStrips,andtheJavastandardutilityclasseswhich
areusedforcollections.
Theregistry
ThenextthingwedoistodeclaretheDeviceRegistry.
Theobserver
PixelPushersregistryusesanObservermodeltotellthesketchwhenPixelPushersappearand
disappear.Theresasimpleimplementationofthisbelow.
classTestObserverimplementsObserver{
publicbooleanhasStrips=false
publicvoidupdate(Observableregistry,ObjectupdatedDevice){
println("Registrychanged!")
if(updatedDevice!=null){
println("Devicechange:"+updatedDevice)
}
this.hasStrips=true
}
}
Thenwedeclareone,likethis:
TestObservertestObserver
Asyoucansee,itsnotabigclass,andjustimplementsamemberyoucanusetocheckwhen
therearestripsavailabletothesystem.Theobserverwillgetcalledandupdatedwheneverthe
arraysshapeorbehaviourchangessignificantly.
Setup
Thentherearesomebitsandpiecesweneedtodointhesketchssetup()method.Thisisa
methodthatrunsbeforethesketchstartsinearnest,anditsagoodplacetoinstantiatethebits
andpiecesweneedforPixelPusher.Thecodeweuselookslikethis:
registry=newDeviceRegistry()
testObserver=newTestObserver()
registry.addObserver(testObserver)
Thisinstantiatestheregistry,gettingitrunningandlisteningforPixelPusherstoappear.It
instantiatestheobserver,andthentellstheregistryaboutit.
Pushingthosepixels
Havingdoneallthissetup,weregoodtogo.Wedoouractualpushinginthesketchsdraw()
method.Firstwehavetowaituntilthereactuallyaresomestripsinexistence!Itmighttakea
secondortwoafterthesketchstartsuntilaPixelPusherannouncesitself.Wewaituntilsome
makeanappearance.
if(testObserver.hasStrips){
//...thePixelPushercodeiswrappedupinhere
}
Whentheymaketheirappearance,wemakeacalllikethistomaketheregistrystarttalkingto
thePixelPushers:
registry.startPushing()
Thenextthingweneedtodoistogetthestrips.TheStripclassisarepresentationofastringof
LEDpixelsoraflexibleLEDstrip.Aswesawearlier,therearegroupswhichcontaincontrollers
eachofwhichcontainsstrips.Sincewalkingthishierarchyistedious,weprovideawaythatyou
canbypassthisandhavetheregistrydoitforyou.
List<Strip>strips=registry.getStrips()
Thisreturnsalistofallthestripsknowntotheregistry.Alternatively,ifyouonlywanttotalkto
oneparticulargroup,youcandothis:
List<Strip>strips=registry.getStrips(some_group_number)
anditwillreturnalistofallthestripsbelongingtocontrollerswhosegroupnumberisgiven.
Thenallyouneedtodoistoloopthroughthestripsandsetthepixelswithinthemtothe
appropriatecolour.Bewarnedthatnotallthestripsmaybethesamelength!TheStripclass
givesyouamethodtodeterminethelength.strip.getLength()willreturnthenumberof
pixelsinthestrip.Tosetthecolourofapixel,youcancallstrip.setPixel(color,
number)wherecolourcaneitherbeaProcessingcolorobjectoraPixelPusherPixelobject.
Inmostofourexamples,wescrapepixelsfromtheProcessingsketchwindowandsendthem
tothearraydirectly.Thecodetodothislookslikethis:
intstripy=0
List<Strip>strips=registry.getStrips()
intyscale=height/(strips.size())
for(Stripstrip:strips){
intxscale=width/strip.getLength()
for(intstripx=0stripx<strip.getLength()stripx++){
colorc=get(stripx*xscale,stripy*yscale)
strip.setPixel(c,stripx)
}
stripy++
}
Normally,theregistrykeepstrackofhowmanypacketsarebeinglost(theygetdroppedifthere
isntenoughbandwidthorifyoureusingawirelessnetworkandtheresnoise)andhowlong
eachPixelPusherissayingittakestopushoutacompletepackettothestrips,andadjuststhe
rateatwhichpacketsaresentautomatically.However,ifyoureonaveryslownetwork,likea
verylongwirelesslinkoracellularmodem,youmightwanttoaddanextraslowdown.Thats
whattheregistry.setExtraDelay()methodisfor.
registry.setExtraDelay(milliseconds)
Thisaddsanextradelaytoeverypacketthatissentbytheregistrysworkerthreads.Ifyousetit
tozero,onlythestandardratelimitingapplies.WithfulllengthHeroicRoboticsstripsandthe
defaultupdaterate,eachPixelPusherconsumesbetween5and10megabitspersecondof
bandwidth.Inthespecialturbomode,aPixelPusherwithtwostripsrunningatmaximumspeed
willconsumeabout52megabitspersecondofbandwidth.
Ifyoureonanetworkwithahigherrorrate,likesomewirelessnetworks,orpoorlyinstalled
ethernet,youmightfindthatyougetpersistentlyhigherrorratesandtheupdatefrequencydrops
uncontrollably.Inthiscase,youmaywanttodisabletheautothrottlingentirely.Weprovidea
registrymethodtodothis.registry.setAutoThrottle(true)willturnautothrottlingon,
andregistry.setAutoThrottle(false)willturnitoff.
Asof20130325,thelibrarydefaultstoautothrottlingbeingturnedoff,soyouwillneedtomake
theabovemethodcalltoturniton.
Ifyoureusingvideosourcematerialandeverythinglookswashedout,youmaywanttoapplythe
antilogcurvecorrection.PixelPusherfaithfullysendseverythingyoutellittoouttothestrips,
otherwise.Asofthe20130608versionofthelibrary,thereisacalltotellittocorrectthe
luminancecurve:registry.setAntiLog(true)willsetthecurvecorrectionon.Thevalue
falsewillturnitoff.ThanksareduetoRusMaxhamforcontributingthiscode.
8. A note on architecture
ThewayPixelPusherslibraryactuallyworksisthatthereareseveralthreads,allrunning
asynchronously.Thedatastructuresusedinternallyarealllockless,sogoodrealtime
performanceispossible.Thethreadsarenamed,soifyouwanttouseVisualVMtoprofile
whatsusingCPUtime,youcaneasilyidentifythem.Thedifferentprocessesarethese:
TheUDPcallback(akaDiscoveryListener)
Theresasmallroutinethatgetscalledeverytimeadiscoverypacketarrives,whichupdatesthe
PixelPusherdatastructures.Itkeepsthestructuresuptodate,andalsonoteshowlongits
beensinceanygivenPixelPusherhasbeenseen.Iftheydisappearformorethanafew
seconds,theyareremovedfromthestructure.Iftheysaythattheyhavemissedpackets(as
indicatedbydiscontinuitiesinthesequencenumbers)thenthisroutineisresponsiblefor
changingtheappropriateratelimitingvariables.
Thepreeningthread
Thisrunseveryfewsecondstocleanthedatastructuresandremoveanysadlydeparted
PixelPushersfromthesystem.
Themarshallingthread(akaSceneThread)
Thisrunscontinuously,andtakescareoftheworkerthreads,makingsurethatthereisone
workerthreadforeveryPixelPusher.ItsresponsibleforkillingthreadswherethePixelPusher
hasdisappeared,andstartingnewoneswhennewPixelPushersappear.
Theworkerthreads(withnameslikeCardThreadfor00:04:13:a3:a6:5c)
EachPixelPushercardhasanassociatedworkerthread.Theworkerthreadissimpleit
checkstheRegistrytoseehowthecardisdoing,andthenitchecksthestripstructures
associatedwithitscard.Ifanyofthemaremarkedasupdated,itwalksthroughthem,sending
themtothecardattheratethathasbeencalculated,andmarksthemasnotupdated.
Thereareseveraldatastructuresinternaltothelibrarywhichareusedtokeeptrackofwhich
cardsarewhich,whichstripsbelongwhere,andwhichstripsarewhichlength.Itisstrongly
recommendedthatyousticktousingthesoftwareinterfaceslistedinthisdocument,ratherthan
modifyinganyofthestructuresyourself,sincethesehavechangedinthepastandwilllikely
changeinfuturewhichwouldrequireyoutowritenewcode!
9. Multi-head operations
Becausetheworkerthreadsonlysendpacketstoupdatepixelsthathavechanged,itispossible
tohavemultiplecontrollingPCs(orMacs,Androiddevices,etc.)onasinglePixelPusherarray,
aslongastheyareeachcontrollingseparatesubsetsofPixelPushers.Itisstrongly
recommendedthatyourestrictthissharingtoonecontrollingPCperPixelPusher,since
otherwisetherearelikelytobetimingconflictsandyoumayendupfloodingonepoor
PixelPusherwithtwiceasmuchnetworktrafficasitdeserves.Ifyoujustcantkeepthe
architecturethissimple,usetheExtraDelayfeaturedescribedafewpagesagotoreducethe
signallingrate.Youwillalsoneedtodisabletheautothrottlesystem,sincethesequence
numberswillnotbesynchronizedbetweendifferentcontrollingPCs.