SIPO Using PC serial port  - Page 1
Forum section: electronics / beginners

author: Albert Luna
author_rank: Newbie
timestamp: February 28, 2021, 01:42:10 am
content: Hello, I am trying to make a Serial-in Parallel-out Register to be controlled by my PC with logic gates and a 74164, 74193, 555 timer. I am programming it through visual basic and I have no problem making the serial communication, I even made a chat (in a prior application) with it and the data is sent correctly but I'm having some issues with receiving the data and keeping it with the logic. The idea is being able to control the data I output to then control a stepper motor.[ Specified attachment is not available ]This is the circuit I have developed so far, the 555 timer has 10,200 hz frequency the serial communication is 9600 bauds, the counter is going to stop at 9 and the clock is going to be activated when a 0 logic so it is starting when the start bit arrives. I have a NAND flip flop to store when to start and it is going to be deactivated when the counter reaches 9, the problem is it is really bugged and I am not sure why it is, when I send any data the 74164 displays 127 or 63 in decimal (0111 1111 and 0011 1111 respectively) and I would like to see if you could help me solving it.

author: MIS42N
author_rank: Frequent Contributor
timestamp: February 28, 2021, 03:10:58 am
content: My first thought is you are feeding a harmonic clock signal, maybe due to ringing in the circuit somewhere causing it to clock a bit in multiple times.Does your clock signal start low and go high half way through a bit? If it starts high and goes low half way through a bit you'll be clocking data while it is changing.The next thought is with the clock (10,200 Hz) running faster than the bits coming in, you may be resetting the system before the last bit of the data is finished. If it is a 0, it will immediately retrigger everything and receive rubbish. This may be solved by running the clock slightly slower than the data rate.Without sitting down and drawing a timing diagram, I think the clock to the 74193 may need to go through an inverter so the 74164 clocks on a low to high and is stable when the 74193 goes from 8 to 9 (with an inverter, that would be half a cycle later).Just thoughts, hope they are helpful.

author: Albert Luna
author_rank: Newbie
timestamp: February 28, 2021, 03:59:37 am
content: How could I sample the data correctly (clock it correctly)? Now that I see the 555 has a delay when it starts until it is stable so resetting it every 8bits does not seem very reliable at all

author: MIS42N
author_rank: Frequent Contributor
timestamp: February 28, 2021, 07:22:53 am
content: a UART does it by using a clock that is a multiple of the receiving frequency, x16 or x64 are typical, running continuously. At the high to low transition a counter starts, counts 1/2 a bit time and samples, thereafter at each bit time. That's complex to implement in discrete logic. I think you would be better off using a microprocessor based system. The uP doesn't need a UART necessarily, it can all be done in software. An ATtiny could do just about everything you want to do. If you need the 8 data bits output the ATtiny can drive a serial to parallel IC correctly.

author: Albert Luna
author_rank: Newbie
timestamp: February 28, 2021, 05:03:28 pm
content: Any other idea?

author: rstofer
author_rank: Super Contributor
timestamp: February 28, 2021, 06:47:46 pm
content: Just an opinion...There's no way to synchronize a signal at 9.6 kHz with a clock of only 10.2 kHz. You are almost guaranteed to have a 1 bit error in each character. As described above, that's why UART clocks are at least 16 times the baud rate.You could possibly improve the situation by running the incoming serial data through 2 D-flops in series clocked by the timer clock. This synchronizes the signal to the timer clock. Google "crossing clock domain". Your input signal is delayed by 2 clocks (more or less) but in the 2d D-flop, it is finally synchronized.If you did use a uC, even a 28 pin Arduino removed from the development board and installed in your own board, you would save on package count, interconnects and board space. You would gain reliability and allow for 'feature creep'.Better yet, use the Arduino Nano and get all the benefits above PLUS the ability to use a USB cable to connect to the PC. No USB->Serial cable or physical serial port required. Very nice...https://www.amazon.com/ELEGOO-Arduino-ATmega328P-Without-Compatible/dp/B0713XK923$7 eachThere's a reason that many of us have walked away from discrete logic in favor of uCs or FPGAs.

author: Albert Luna
author_rank: Newbie
timestamp: February 28, 2021, 11:56:43 pm
content: Could you recommend any book on digital electronics?

author: gnuarm
author_rank: Super Contributor
timestamp: March 01, 2021, 12:40:56 am
content: Quote from: Albert Luna on February 28, 2021, 03:59:37 amActually, you want a longer delay on the trigger. The trigger happens at the beginning of the leading edge of the start bit. You should sample somewhere in the middle of each bit. I think that longer time at the start of the 555 cycle is near perfect the extra half bit you need for the first time... unless you are triggering on the wrong edge of the clock. I don't use the 555 much, so I don't recall the output waveform you will get.Do you have any images from a scope trace?

author: gnuarm
author_rank: Super Contributor
timestamp: March 01, 2021, 12:42:07 am
content: Why 10.2 kHz rather than 9.6 kHz?

author: Albert Luna
author_rank: Newbie
timestamp: March 01, 2021, 01:51:21 pm
content: of the 555 timer you mean

author: gnuarm
author_rank: Super Contributor
timestamp: March 01, 2021, 05:49:32 pm
content: Quote from: Albert Luna on March 01, 2021, 01:51:21 pmYour data clock should match the bit rate as exactly as it can. If you start sampling in the center of a bit and clock 10 bits the timing errors add up. If you assume the same error size with opposite directions on each end and do the math you will find a limit of less than 2.5%. Of course if all the error is on one end it can be as much as 5% and work. 10.2 kHz is 106.25% of 9.6 kHz. When I simulate your circuit I get 9.5 kHz, so not too bad. It will be very hard to get a capacitor to be the value you need to 1-2%.Otherwise the circuit is not too bad. The starting state of the 555 timer is with the cap completely discharged, so the first cycle out is a bit more than 1 clock cycle putting the sampling time about a third of the way into the bit.Your drawing shows an RS-232 connector. I assume the signals are actually 5V logic signals and not RS-232 signals at ±5 to 12 volts? That could damage your circuit.Normally a free running clock is used that is 8 or 16 times the bit rate. This clock controls a start detection circuit that watches for the initial falling edge, then samples on each clock until half the bit time has passed (either 4 or 8 clocks). Even sample has to be low to treat it as a valid start bit. Then the bit times are counted (8 or 16 clocks) and the data collected. It is customary to sample a 9th bit time after the start bit to verify the line has returned to a '1' state meaning there was no timing or "framing" error. You can do this with a counter that starts at the mid bit count (4 orand counts down when a character is being received. On reaching zero the carry out is used to enable the other circuitry to shift in the bits and the counter is loaded with a new start value if the last bit or wraps around for the rest of the bits.This would mean your 555 timer is replaced by a more complicated circuit using another counter chip. You still need a timing source, but at 9,600 x 16 or 153,600 Hz. The output of the NAND gate FF would be applied to the LOAD- input with the D0:3 inputs wired for an 8 count. The TCU output would be used to clock U2 and U5. Does that make sense?That still leaves you with a need for an accurate timing source. It is hard to get 1-2% without a crystal. Where is the data coming from? Maybe you can provide a clock along with the data?

author: Ian.M
author_rank: Super Contributor
timestamp: March 01, 2021, 08:06:22 pm
content: The problem is timing accuracy.Consider a typical character from a UART with 8N1 RS233 compatible framing, Also lets use logic levels, not RS232 line levels.Note that:The signal idles high.All the bits are equal length: bit_time=1/baud_rateTaking all timing from the start bit leading (low-going) edge, and in units of bit_time, we need to sample bit0 at t=1.5, bit1 at t=2.5, bit2 at t=3.5, ... and bit7 at t=8.5. If the bit7 sampling time is outside the window t=8 to 9, we'll get invalid data, either bit6 or the stop bit.Therefore the absolute maximum baud rate mismatch we can tolerate if the signal edges were perfect is for our RX clock to be 5.88% slow or 6.25% fast relative to the TX baud rate.However, there can be baud rate errors on both ends, depending on the master crystal used and the exact division ratio to get the TX clock, so if you are working with MCUs, and to allow for limited bandwidth of the link giving a worst case risetime of 10% of the baud rate (so the valid 'window' for bit7 is t=8.1 to 8.9), you need to be within 2.35% of the nominal baud rate. Anything over +/-2% clock error is pushing your luck, as it may be out in opposite directions at each end of the link.Fortunately PC UARTs have much better clocks and at most standard IBM PC baud rates you can count on under 1% error. It will almost certainly be a lot better, as good as the crystal clocking the UART if that crystal frequency is well chosen#, and its a motherboard port. That gives you +/-3.7% worst case clock error tolerance for your peripheral device which is achievable if you hand-trim the 555 frequency.To do so, send a character with bit 7 clear and bit 6 set, e.g. any capital letter repeatedly in a loop, with a short delay (> one char) in between, and monitor bit 7 from your receiver circuit while adjusting the oscillator, to find the two points where bit 7 goes high nearest to the nominal baud rate. Set the adjustment midway between them.# See Table III on page 15 of theN.S. PC16550DUART datasheet, which was used from the introduction of the IBM PS/2. Later chipsets with integrated UARTs almost invariably implemented a 16550 compatible one.

author: rstofer
author_rank: Super Contributor
timestamp: March 01, 2021, 09:25:06 pm
content: There are a lot of FTDI USB<->Parallel Port, with and without a FIFO. This is a much cleaner solution.

author: MIS42N
author_rank: Frequent Contributor
timestamp: March 01, 2021, 10:05:55 pm
content: Why do this with discrete logic? I needed an extra serial input to a PIC processor that had only one inbuilt UART so I wrote a software receiver. It uses 4 bytes of data and just over 50 lines of assembler to do the job. This could be done on just about any small processor using whatever the instruction set is available and adjusting for the internal clock (I suggested ATtiny before, but that's because they are cheap and available). If the data is required as the 8 parallel bits the processor can control a serial to parallel chip, or use a processor with sufficient output pins.Doing it with logic ICs is always going to be complex and needing careful design. There are so many simpler ways, why not use one of them?

author: Ian.M
author_rank: Super Contributor
timestamp: March 01, 2021, 10:09:27 pm
content: Certainly, but some people still get a masochistic 'hair shirt' satisfaction from doing it with oscillators or monostables and raw logic. I cooked up something workable under LTspice as a beer-bug lockdown distraction. Input and output *SUCK* at the moment but it does receive and latch 9600 baud serial data.Edit: rename the .plt file without the extra .txt extension. You need it to display the logic levels of the sim result.I suspect it could be reduced to four ICs, a 74HC595 as the SIPO shift register/latch, a quad gate for clock gating and as a SR flipflop, a 74HC4017 decoded decade counter for sequencing and of course the 555, preferably a CMOS one.

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 01, 2021, 10:54:51 pm
content: Note that the cheap ($5 USD) Pro Micro microcontrollers sold on eBay, based on ATmega32u4 microcontroller, can be programmed using free open source tools, either in the Arduino environment (as Arduino Leonardo – these have the Arduino Leonardo bootloader (and not Arduino Pro Micro or Atmel DFU), but with a Sparkfun Pro Micro pinout), PlatformIO, or on bare metal using avr-gcc and avr-libc. These have a native USB controller implemented inside the microcontroller, so they can become any USB 2.0 LS (low speed, 1 Mbit/s) or FS (full speed, 12 Mbit/s) device. There is no FTDI chip, no serial-to-USB bridge, and no particular drivers needed. These are often used to implement HID devices – keyboards, mice, joystics – and MIDI devices. (The single microcontroller can provide more than one endpoint, for example both an USB Serial and USB Keyboard device.)To program these, all you need is the Pro Micro clone and an USB cable (USB to micro-USB). Power is provided by the computer (or USB cable), and both normal communications as well as programming (flashing) is done via the USB cable. (Of course, you also need a development environment for your computer, but those are freely downloadable from the internet.)If you add an ADuM4160/ADuM3160 USB isolator (clone) between the Pro Micro and your computer, you can protect your computer from many mistakes, like accidentally grounding the microcontroller to the wrong ground potential or short-circuiting the USB VCC and GND. These cost around USD $10, but as they are basic implementations of the ADuM4160/ADuM3160 datasheet schematic, they seem to be pretty acceptable implementations for this kind of stuff. (Note that many of them have a small DIP switch to choose between low-speed/LS (1 Mbit/s) and full-speed/FS (12 Mbit/s), you generally want it to be in the full speed position.)The USB Serial device looks like a standard COM port to Windows (and a standard serial device in other operating systems), but baud rate, bits per byte, and the number of stop bits are all irrelevant; not used. Even a simple Arduino sketch can transfer about 1,000,000 bytes per second continuously from the machine to the microcontroller, or vice versa. (Ping-pong is a bit more complicated, as although USB is full duplex, the details on how the software on both the computer and on the microcontroller handles the transfers dictates how much of the theoretical bandwidth you can achieve; and usually depends on whether you can keep data flowing, or have to do a query-response type thing.)The USB Human Interface Device (HID) protocol does not need any special drivers, but the data rate is capped at 64,000 bytes per second (somewhat less in practice, as you can send one packet of up to 64 bytes every millisecond).The pinout on these Pro Micro clones is(micro-USB)(TXO) PD3 TX RAW (RAW)(RXI) PD2 RX GND (GND)(GND) GND RST (RST)(GND) GND VCC (VCC)(2) PD1 SDA PF4 (A3)(3) PD0 SCL PF5 (A2)(4) PD4 PF6 (A1)(5) PC6 PF7 (A0)(6) PD7 SCK PB1 (15)(7) PE6 MISO PB3 (14)(8) PB4 MOSI PB2 (16)(9) PB5 PB6 (10)where the pin label on the board is in parentheses, andPxnmeans GPIO bankxbit/pinn.An Arduino sketch that puts each byte written to the USB Serial port to pins (3), (2), (RXI), (TXO), (A3), (A2), (A1), and (A0), listed from least significant bit to most significant bit, would be rather trivial. This also reserves (4) and (6) (although you could use them as inputs), so it uses both UART and I2C pins, but leaves the three SPI pins and five other pins unused, for you to perhaps use for some other purpose.Code:// SPDX-License-Identifier: CC0-1.0// Choose "Tools" > "Board" > "Arduino AVR Boards" > "Arduino Leonardo"static uint8_t mask;void setup() {Serial.begin(9600); // Does not matter for ATmega32u4pinMode(3, OUTPUT); // PD0 (3) Data bit 0pinMode(2, OUTPUT); // PD1 (2) Data bit 1pinMode(0, OUTPUT); // PD2 (RXI) Data bit 2pinMode(1, OUTPUT); // PD3 (TXO) Data bit 3pinMode(21, OUTPUT); // PF4 (A3) Data bit 4pinMode(20, OUTPUT); // PF5 (A2) Data bit 5pinMode(19, OUTPUT); // PF6 (A1) Data bit 6pinMode(18, OUTPUT); // PF7 (A0) Data bit 7pinMode(4, OUTPUT); // PD4 (4) Mask bit 4pinMode(6, OUTPUT); // PD7 (6) Mask bit 6mask = 0;}void loop() {// Loop whenever we receive data via the USB Serial portwhile (Serial && Serial.available() > 0) {uint8_t data = Serial.read();uint8_t d = (data & 15) | mask;uint8_t f = (data & 240);// Update the GPIO banks with as little delay between the two as possible.PORTD = d;PORTF = f;}}The two "mask" pins, (4) and (6), are also in the D bank, and we update the states of all D and F bank pins at once, so that's why they're included above even though we don't use them for anything. If they are used as inputs, then mask value determines whether the internal pull-up resistors are enabled for them or not.ATmega32u4 has 2560 bytes of RAM, and in the Arduino environment, the above sketch uses only 150 bytes (leaving 2410 bytes of RAM unused). The sketch uses 3818 bytes, or 13%, of the available Flash (read-only/code memory). So, there is definitely room to extend the program. The 5V Pro Micro clones run at 16 MHz, and the 3.3V ones at 8 MHz; I prefer the 5V ones. (The 5V ones use 0 to 5V logic states on the pins, and the 3.3V ones 0 to 3.3V.)There are other, perhaps better and cheaper microcontrollers out there, but I believe the old ATmega32u4 is a good introductory device, being a simple 8-bit AVR architecture, but with a native USB interface.

author: Ian.M
author_rank: Super Contributor
timestamp: March 27, 2021, 11:30:54 am
content: My beer-bug lockdown distraction (reply #14 above) has grown a LTspice behavioral UART data generator that converts a number (expressed as a voltage 0V-255V) to raw UART output with 8N1 framing at whatever baud rate you specify!I've also added a R-2R DAC to aid comparing the output to the test signal input.Copy the.plt file from #14, and rename it to Ser2Par2.plt then when you run the sim, add a plot pane to viewV(DACout)andV(Test)/127VEssential reading:http://ltwiki.org/?title=Undocumented_LTspiceand the LTspice help file!