-
• #2
In the anonymous function in your
onInit()
code I would expect thedisplayPixel()
first and then thedigitalPulse()
for the latching (flank) and (combined?) the output enable for a particular time (apply the power to the coil)... - in other words, flip the lines28
and29
, and allow a much longer pulse...What type of shift register are you using?
Btw, you can save yourself some work by using MC / Eespruino built-in SPI (serial peripheral interface) appliance: assuming, there are two shif registers, one for x (0..5) and the other one for y (0..6) and the shift registers are in series - first x, then y - then you have an easy game:
// SPI1 and ports for Espruino Pico / Wifi and 74HC595 shift registers SPI1.setup({mosi:B5, sck:B3}); // SPI1, other SPIx can do too var dnss = A0; // nss pin used for the latching, var pls = A1; // for the _OE (neg output enable) var dat = new Uint8Array(2); function setPxl(x,y,p) { // polarity 0,1 x=Math.floor(x); y=Math.floor(y); // optional x=(x>4)?4:(x<0)?0:x; y=(y>6)?6:(y<0)?0:y; // optional d[0]=Math.pow(2,y); d[1]=Math.pow(2,x); d[p]^=0xFF; SPI1.write(d,dnss); digialPulse(pls,1,10); }
-
• #3
There is 2 ic 74hc238 who are decoding a 3bit adress and convert to 8bits for the shift register 74hc595 (i suppose) for l293d
I do not have direct access to shift register.
But perhaps i'm wrong on the way that's works.
Or in a different way.
The 595 is a stronger version of standard shift register...Here the git page of the project (lib and diagramm)
In the arduino lib, the latch time is 500 microseconds.
I've tried with more time but no better results...An other question who is alway confuse me on the espruino.
I want to use the usb for debugging purpose,
The display is powered in 12v and convert a line to 5v to power the mcu.
i need to power the espruino from this line.
On which pin do i need to clip the power (i'm not soldering at the moment)
On the pin near the gnd one or the next pin (third) or on the ViN pin?
I'm sad cause i've burned two display with an incorrect power connection when changing clip position from the mcu.
Regards -
• #4
If i power the espruino with the 12v, i plug on the 3rd pin (gnd pin side)?
Apologies for this basic question, but the page is not lighting for my english abilities 😞 -
• #5
Hi - which Espruino board are you using? I'm pretty sure the 3rd pin won't be right (that's usually the 3.3v pin) - I think if you do that you could cause some serious damage!
I'd also make sure that GND of all boards is connected together - it can often be a big cause of problems if that isn't connected.
In terms of software, what you're doing looks good. The latch is often active low though, so I'd try:
digitalWrite(LATCH_PIN,0); displayPixel(aff%5, Math.floor(aff/5)%7, compteur%2); digitalWrite(LATCH_PIN,1);
Or potentially the problem is that
digitalPulse
is asyncronous? It will be working while you are writing data using displayPixel. I'm not sure if that's your intention? If not:digitalPulse(LATCH_PIN,1,1); setTimeout(function() { displayPixel(aff%5, Math.floor(aff/5)%7, compteur%2); }, 2);
Might help?
Also, I believe there are some issues with shiftOut:
- It will shift out MSB first (you need to flip the byte first with E.reverseByte)
- By default it will only shift one bit. The docs are a bit cryptic (http://www.espruino.com/Reference#l__global_shiftOut) but you need
repeat:8
in the options.
You could try this?
shiftOut(DATA_PIN, {clk:CLOCK_PIN, repeat:8}, [E.reverseByte(data)]);
Or, as @allObjects says, you can use the SPI object. But you'll still need
reverseByte
- It will shift out MSB first (you need to flip the byte first with E.reverseByte)
-
• #6
@Mrbbp, I see that you use a controller (with 293 type, 4 x half-H bridge)... a lot of hardware, but it makes it possible to drive the coils w/ 12V and the logic with 3.3V (or 5V), and with the tons of diodes it is a pretty cool setup - and so is obviously the driving software.
From my understanding, the shift register is there to feed the two 238 3-to-8 decoders, and the pulse is only there for the write (latch) into the shift register output buffers. Regarding the pulse: the shift register requires only a raising flank, and we get hat for free by using the built in SPI appliance and the nss (negative signal select) pin in the
.write()
. The nss pin you connect to the board's write input (which is the output register latch clock of the shift register) - NOTE: Im referring to the Version 2-5 of the driver board which you obviously have...To drive the row and column decoders, only 3 bits each are used for each nibble (half a byte, half of the shift register's 8 registers). The fourth bit is used for the data of the selected row and column, respectively. These 4th bits are always low and high or vice-versa for making a change. In other words, the byte you have to send (with SPI) looks like this:
+---+---+---+---+---+---+---+---+--+ |MSB| | | | | | |LSB| <--- Most/Least significant bit | H | G | F | E | D | C | B | A | <--- Shift Register Outputs QX |128|64 |32 |16 | 8 | 4 | 2 | 1 | <--- bit weight in decimal | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | <--- bit pos | | | | | | 0 | 1 | 2 | <--- col address bit (3x) | | | | |H/L| | | | <--- col data bit (1x) | | 0 | 1 | 2 | | | | | <--- row address bit (3x) |L/H| | | | | | | | <--- row data bit (1x) +---+---+---+---+---+---+---+---+--+ | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |64| dec 164 flips row2/col1 pixel | | row 2 dec | | col 1 dec | | +---+---+---+---+---+---+---+---+--+ | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |44| dec 44 flips row2/col1 pixel back | | row 2 dec | | col 1 dec | | +---+---+---+---+---+---+---+---+--+ | 0 | x | x | x | 0 | x | x | x | 0| dec 0 and 255 'de-power' the coils +---+---+---+---+---+---+---+---+--+ because BOTH of their ends | 1 | x | x | x | 0 | x | x | x | 1| dec 255 are driven to same voltage, +---+---+---+---+---+---+---+---+--+ level either L or H; pref. L, therefore preferably 0. Altenative: nssPin.reset(). Unit uses about 50..70/60..90mA idling and 250/350mA on active (9/12V). NOTE: Counting of rows and columns starts with 0.
The idea of the flip dot display though is that it does not use current after setting a(ll) dot(s). Therefore, after updating the whole display, at least these row and column data bits have to be set to low. Depending the implementation, I recommend to do that even between pixel settings... In other words, the data has to be stable (latched) in the shift register output register buffer for a specified time... and you have to figure out how long that time is.
I find it odd that the addresses are reverse (MSB shifting out first), but it is not that much a complication for the code. Regarding the max. invocation frequency, you may need to look if you can set one pixel after the other, because if you keep the values not stable for required time, the 'derived pulse' - the time between two pixel flips - is too short to actually have the pixel flipped... But if you de-power the coils after a sequence of settings, you may even choose a higher voltage - up to 36 volts according to the L293 spec - to 'pump' enough energy into the coils with a much shorter time of applying stable values (and before de-powering)!
SPI1.setup({mosi:B5, sck:B3}); // SPI1, other SPIx can do too var nssPin = A0; // nss pin used for the latching function setPix(x,y,p) { // x(col),y(row),polarity 1/0 or true/false SPI1.write( (E.reverseByte(y | (x<<4))>>1) | ((!p) ? 128 : 8), nssPin); }
That's all you need... the nssPin is connected to the
write
(RCLK
) of the 595 shift register. The raising flank of the nssPin does just the right thing...Init your 3 pins - data, sclk, rclk - as output and set rclk high and you are just fine from the get go.
If you loose flips, you may slow down the
setPix()
invocation frequency... To do that in the Espruino way, you do it event driven and in a producer/consumer pattern. You create a queue that is shared between producer and consumer. The producer -setPix()
calculates and stores the values, and kicks the consumer off if it is the first entry in the queue. The consumer does the actual write to the device and works after initial kick off interval driven until everything written, including the de-powering value. The queue or buffer you implement as ring buffer to avoid memory management... (overflow detected, but not handled yet in the code).SPI1.setup({mosi:B5, sck:B3}); // SPI1, other SPIx can do too var nssPin = A0; // nss pin used for the latching var rbuf = new Uint8Array(512); // ring buffer w/ fill counter cnt... var cnt = rpt = wpt = 0; // ...and read/write buffer pointers function setPix(x,y,p,h) { // x(col),y(row),polarity 1/0 or true/false if (++cnt <= 512) { rbuf[wpt] = (E.reverseByte(y | (x<<4))>>1) | ((!p) ? 128 : 8); wpt++; if (cnt === 1) (setInterval(wriPix,1); // make/invoke it 'async' } else { cnt--; // throw error, decide what to do } } function wriPix() { var v = rbuf[rpt]; SPI1.write(v, nssPin); if (cnt > 1) { // more to write setInterval(wriPix, 2); if (++rpt >= 512) rpt = 0; cnt--; } else if (v) { // was last one, de-power setInterval(wriPix, 2); rbuf[rpt] = 0; } else { if (++rpt >= 512) rpt = 0; cnt--; } }
If you want to make the code 'safe' to prevent the coordinates not to interfere with the row and column data bits, use this expression which mask everything beyond 3 row and column address bits (works even when coordinates are not integers...):
(E.reverseByte((y&7) | ((x&7)<<4))>>1) | ((!p) ? 128 : 8)
Btw, choosing
!p
makes it 'color'-safe: 0 and just any thing else...PS: will test the code when I get a display... ;-)
-
• #7
@allObjects: Whao, i'm impressed! Amazing!
Have to take time to test your code.
Thanks for the great explanation.
I've got the version with the silkscreen error on pcb (inverted LAT and 5V pins).
Sorry i just understand the use of espruino spi.write() - data,clk, latch pins@Gordon, sorry, i've forgotted to write: i use a pico board unpinned.
The arduino lib is great but for english writer, no accents! :/
Want to combine with the custom font of espruino. -
• #8
@Mrbbp no problem :) You want to connect your input voltage to what's shown as
BAT_IN
here: http://www.espruino.com/Pico#pinoutIdeally just the 5v signal from the board though if you can, rather than 12v.
-
• #9
PS: will test the code when I get a display... ;-)
...was a hint looking for a sponsor... ;) - and kind of says: sorry, have (had) no chance to test... of course, I could make a dry test: print the bits I'm passing to
SPI1.write(...)
, but that part I actually already use successfully as outlined below.I'm tinkering along on a different display 'project' as possible 'sub-project' or 'explorative project' for an other, larger project. Im tinkering with a retro display: National Semiconductor 12 digit 7-segment, red LED Bubble Display NS A5120A (see attached pic) - as found in many pocket calculators in lat 60/early 70 - about $2K a piece was HP's first usable/scientific pocket calculator.
I use 3 595 shift register in series. The last one sources the 7-segment plus decimal point anodes, and the 12 bit of the 16 bits of the other two drain the common cathodes for each digit... since the shift register drains a measly 6ma on 5V, I'm already in trouble with just 595 and may need to add 12 transistors to reliably drive all segments plus decimal point of a single digit all at once... another 2 chips of ULN2703 or 12 plain transistors w/ 12 Base resistors (the issue is obviously not the driving of the cathodes, - otherwise you could not see the digit lit - but more so the reliable shifting on higher speeds to 'hide' the multiplexing from the slow eye. The heavy drain load makes the latching register not to behave nicely anymore...).
The setup you see in the picture uses an Espruino-Wifi, which is more or less a Pico w/ onboard ESP8266 (latter here not in use right now even though the blue LED dims...). Also you see that only the drains of tje first 3 digits' are hooked - hidden under the white-blue-striped segment wires (Ran out of common cathode resistors from my reuse-pile... or rusty nails I keep for ever... ;) ...to the dismay of many around me...). I avoid the
E.byteReversed()
in digit's common anode driving, sothink
reversed. You see only 1 digit displayed because the digits are time multiplexed with very low frequency.The
SPI1.write(...)
that produces 'this' output is equal to:// Segments 12 Digits, 1st is 'on' (=0=drains) // for 5 on ------- ---1 SPI1.write([0b01101101,0b1111111,0b11101111],B0); // 595 right middle left // latches latches latches // 1st byte 2nd byte 3rd byte // receives receives receives // data last data 2nd data 1st
Regarding the SPI write with nss pin passed: SPI slaves requires the slave select line to go and stay low - hence called - nss (negative ss) in order to make a slave look at data on the bus (MOSI - Master Out Slave In wire) and detect when the transmission transaction is completed: ssn goes high. You can control ssn by yourself separately, such as
B0.reset()
(assuming ssn connected to B0), then do multiple sends withspi.write(aSingleByteOrAnArrayOfBytes);
and conclude the 'transaction' withB0.set()
. For convenience, @Gordon implemented thespi.write()
with nss in addition to accepting an array of bytes and not just a single byte - lest to talk about multiple pins - so that when you have all of your things to send ready-made in one byte array, you just need one call - which makes thing just crazy fast, because it is executed 'down deep in the belly' of Espruino all at once rather than in piece meal, spoon fed...
1 Attachment
-
• #10
I'm back on subject with some news and questions.
I've tested @allObjects's code. I've got strange behavior of the picoboard: pb to upload code, have to unplug+plug to handle the board.
with a simple loop to flip one pix at a time, i've got the same behavior than with my previous code. Some dot flips in random order...
I have retest some code with an arduino, and it work very accurately.
My question is about logic level (3.3v vs 5.5v) with shift register et encoders... is it possible that the strnage behavior is due to this shifting?
I've bought online this night a shift level breakoutboard.
I will retried with it at the end of the week.
so wait and see.@allObjects: You use
A0
pin for the latch (nssPin) do i need an Analog Pin? On the pico board, the size of this pin is smaller (difficult to clip or solder), therefor i use an other pin. is it a pb?
You've writtenInit your 3 pins - data, sclk, rclk - as output and set rclk high and you are just fine from the get go.
Do i need to explicitly use
pinMode(xx, 'output')
? and anopenDrain
argument for the nssPin?
Thanks for your time.regards
-
• #11
I've decided to work by a different way. Too many time lost on that.
I'm connecting the espruino to an arduino which control the flipdot display trough a serial wire to transfer an arrayBuffer. -
• #12
...sorry to hear that... but it is for sure a nice experiment to let an Arduino do the bit work and Espruino the byte work. I do not know about the powering... that could be an issue, because the flip dot things are a lot of electromagnetic things (coils) that can 'fire back'
Regarding the pin for nss, you can pick any that is available and easier in access to you.
Also note that there was actually something that changed for 1v95 with which I had some glitches when changing pin mode. A good practice is to always intentionally setting the pin mode even though Espruino tries and does it pretty well automatically for you.
If you take a closer look at my intial and then later code with all this shift out, I had every state in its own timeout to give enough time to let enough energy flow thru. @Gordon then adviced me to just run it all the way thru... to reduce the flicker... This works for electronic devices, such as LEDs, but for sure not for ELECTROMAGNETIC devices, which need a certain pulse width to let enough energy flow. This may be the cause of the irregular flips...
Sorry not seeing your previous post earlier...
-
• #13
Ok, soooo i did it.
Espruino (Pico) for drawing text + Arduino (Nano) for controlling through a serial com @19200Arduino code
[#include](https://forum.espruino.com/search/?q=%23include) <FlipDot_5x7.h> [#define](https://forum.espruino.com/search/?q=%23define) CLOCK 13 [#define](https://forum.espruino.com/search/?q=%23define) DATA 11 [#define](https://forum.espruino.com/search/?q=%23define) LATCH 10 int dataReceived = 0; /* Wiring: OUT Not connected to Arduino 5V 5V LAT LATCH GND GND SCL CLOCK SDA DATA GND GND 12V VIN 12V VIN Change false to true if the color is inverted. */ FlipDot_5x7 flipdot(1, 1, false); int liste[35]; boolean flag = false; int nItem = 0; int temp; void setup() { // serial vers sepruino Serial.begin(19200); delay(100); // to initiate serial Serial.print(""); // flipdot.begin(DATA, CLOCK, LATCH); flipdot.fillScreen(FLIPDOT_YELLOW); flipdot.display(); delay(1000); flipdot.fillScreen(FLIPDOT_BLACK); flipdot.display(); // to begin data sending Serial.write("@"); } void loop() { delay(10); } void ecrit() { // draw dot by dot for (int i = 0; i < 35; i++) { flipdot.drawPixel(i%5, int(i/5)%7, int(liste[i])); } // show on display flipdot.display(); flag = false; // empty array liste[35]; } void serialEvent() { // for debugging purpose temp += Serial.available(); while (Serial.available() > 0 && !flag) { dataReceived = byte(Serial.read()); if (dataReceived == 0x3E) { // if endMark Serial.flush(); // for debugging purpose /*Serial.print("n bytes recus: "); Serial.println(temp); for (int i=0; i<35; i++) { Serial.print(liste[i]); } Serial.println("");*/ nItem = 0; temp = 0; flag = true; // show on display ecrit(); } else { // invert color if (dataReceived==0) {dataReceived=1;} else {dataReceived=0;} // fill the array with datas liste[nItem] = dataReceived; nItem++; } } }
Espruino code
var compteur = 0; var g; var longT; var texte = "The wind was rising, the wind was falling, lifting up her ugly wool skirt."; Graphics.prototype.print = function() { for (var y=0;y<this.getHeight();y++) console.log(new Uint8Array(this.buffer,this.getWidth()*y,this.getWidth()).toString()); }; function sendDatas() { if (compteur < -longT) { compteur = 7; console.log("reset compteur: ",compteur); } g = Graphics.createArrayBuffer(5,7,8); g.setFont4x6(); g.setBgColor(1); g.setColor(1); g.drawString(texte,compteur,-1); var datas = new Uint8Array(g.buffer); if (compteur === 0) { longT = g.stringWidth(texte); console.log(compteur, longT); } Serial1.write(datas); Serial1.print('>'); //g.print(); LED1.toggle(); compteur--; } function onInit() { require("Font4x6").add(Graphics); Serial1.setup(19200, {tx:B6,rx:B7}); // wainting for init of serial com from arduino before to send datas Serial1.on('data', function(e) { console.log("serial In:", e); if (e == '@') { setInterval(sendDatas, 100); Serial1.removeAllListeners(); } }); USB.setConsole(); }
a video of the display in action
https://www.instagram.com/p/BeeN2OCAVyw/ps: i've fried 5 dots, therefor i've removed the dots on the display (upper line)
-
• #14
ERROR fix of core line in code fragments in post #6:
Polarity ('color') is set by either bit 3 or 7, which have the values 8 and 120, respective (and not 64 and 128, which would be bits 6 and 7), in order meet the spec (paraphrased):
Data byte has to be xxxCyyyc where xxx is the binary representation of
the x and y coordiantes). c is the color, w/ C is the inverted of c to drive
the bridge +to- or -to+; for example, x = 2, y = 3, c = 1 would be 010 0 011 1
(and reversed when using SPI.write() for the shift-out...).... SPI1.write( (E.reverseByte(y | (x<<4))>>1) | ((!p) ? 128 : 8), nssPin); ...
Recap of wiring:
Espruino (Pico - 5V tolerant, since flip-dot is 5V driven) to http://www.hannio.org flip-dot-disaplay module (using SPI):
- GND - GND
- MOSI - SDA
- SCK - SCL
- nssPin - LAT (any pin works)
FlipDotDisplay (has 5V regulator on board that supplies the logic):
- GND power source - GND
- 12V power source - 12V
*** DO NOT connect any 5V or 3.3V between Espruino and FlipDotDisplay - when Espruino powered (USB or Bat).***
Flip-Dot-Display module though supports 5V at the 5V pin... which could be used to drive Espruino over its BAT in / USB. Powering Espruino from 5V of Flip-Dot-Display module allows to work with single 12V power supply...
Code used to create attached clips:
// flipDot00.js var nssPin = A0; // nss pin for LAT (latching) var mosi = B5; // mosi / serial data pin for SDA var sck = B3; // sck / serial clock pin for SCL var spiFdd = SPI1; // SPI# compatible w/ mosi and sck pins for Flip Dot Display pinMode(nssPin,'output'); nssPin.reset(); spiFdd.setup({mosi:mosi, sck:sck}); // SPI1, other SPIx can do too function px(x,y,p) { // x(col),y(row),polarity 1/0 or true/false spiFdd.write((E.reverseByte(y | (x<<4))>>1) | ((!p) ? 128 : 8),nssPin); } function fdSetAll(p) { for (var c=0;c<5;c++) for (var r=0;r<7;r++) px(c,r,p); setTimeout(function(){nssPin.reset();},10); // de-power } n = 0; wi = null; function f(i) { // flip all every i milliseconds var p=false; if (wi) s(); wi = setInterval(function(){fdSetAll(p=!p);},i); } function r(i) { // run thru byte w/ inc i // wi = true; in console before r() if (wi) s(); wi = setInterval(function(){spiFdd.write(n=(n+i)%256,nssPin);},0); } function s() { // s(); in console stops both, a() and r() and depowers if (wi && wi !== true) clearInterval(wi); wi = null; nssPin.reset(); }
PS: Great Thanks to @Mrbbp who provided me with two units to validate and have fun...
4 Attachments
- GND - GND
-
• #15
Gorgeous!
Bravo @allObjects.
Thanks so much for your work.Have you try to chain 2 flip dot display?
How to screen something on one display and follow on the second one?
In the arduino's lib, it seems possible.
On the hannio github, there is a schematic to chain two flipdot. -
• #16
...hold your horses...
Eis nach em andere, wie z'Paris! (Bernois... as it connects to France)
Chaining... sure: easy... out of one goes to in of next (daisy-chained), clock and latch (and ground and 12V power) go parallel...
Nest step is to connect it to a Graphics buffer...
With a configurable setup any cascading should be possible. Configurability may though have an impact on update speed. Will see.
-
• #17
... oder langsam ächli pressiäre (... or slowly gearing up)
-
• #18
...iuuu - seit dr Matte Giuuu
Hello @Gordon
I've bought a flipdot display controled by a shift register.
There is an arduino lib to control it...
i find the code to display one pixel with arduino:
it needs a LATCH pin more for working, i've added it in the js code
i've rewrited the code for espruino like this
it does not work...
if i generate a random number for data
dots flip sometime...
i suppose it's about format of my byte...
Luca from Hannio send me the format for the byte
Where i'm wrong?
best regards
é.