Need a 1-wire type protocol

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All -

I need to control 9 bi-color LEDs as cheaply as possible. Actually, 9 groups of 9 bi-color LEDs, 81 total, but it should be a lot easier to handle them 9 at a time.

I've almost finished a little charlie-plexing design using 5 pins of an attiny12, which leaves 1 pin to communicate with. At $1.72ea from Digikey, this seems to be the cheapest way to go. Much more so than a Maxim LED driver like the 7219 ...

Data would be one-way from the host AVR to the attiny12 only. Really just telling it which LEDs to turn on/off. The attiny will just sit in a loop cycling through the on/off data for the LEDs and twiddling the pins appropriately.

So, I need a simple one-way one-wire protocol. It would have to be timing-based since it's only a single pin. I'm thinking of something similar to the standard TWI/1-wire protocol, but was wondering if anyone had any better ideas, or better yet, implementations ?

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TWI is two wire, one for clock and one for data.

You can do a simple PCM, using presence or absence of pulses at expected times, or pulse-width. Dallas/Maxim 1-wire has added complexity because of trying to supply both power and data over the single pin.

Idea: Unique "start bit" (maybe longer than any other allowed bit). Follow that with pulses at regular times and make them wide/narrow depending on the bit value. This would self-clock nicely and the software would be relatively simple. The receiver could trigger by interrupt on leading edges of pulses, reducing the clock requirements a LOT. Then, it would simply be a matter of determining whether the plulse width is short, long, or really long.

One important factor is data rate which you have not specified. If it needs to be above 100Kbit/sec or so, software is more of a challenge; if below that, it is more practical for bit-bang.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

UART in one direction is one wire (and GND).
AFAIK there is a 9bit mode with UART.

But i´d control all 9 x 9LEDs with one wire: Address and data via UART....

Klaus
********************************
Look at: www.megausb.de (German)
********************************

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dang - 11am and my brain is still fuddled. I meant the Dallas 1-wire, not TWI/I2C. I also just realized that the ATtiny11 has an internal 1MHz clock too, and it's a LOT cheaper. $0.54 at Digikey - better and better.

Software rate won't be fast. Maybe 100 updates/sec at most - enough to spin a rotary switch and have the ON LED go across a row of 9 nice and quick. Can use PB1/INT0 for input and just maintain a timer count to measure pulse widths - easy.

Watch for a falling edge, time the pulse, and if it's within the start-bit time window, start counting pulses. Short pulse = ON, long pulse = OFF. 18 pulses later we have the new configuration.

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, an added wrinkle to this. I need to be able to talk to NINE ATTinys from the main AVR. So I can't really just use a uart. So I need to wiggle 9 pins on the main AVR. Say the "clock" rate is 1T, then a 0-bit would be 1T and a 1-bit would be 2T. Or vice-versa.

Reading around a bit on protocols, it seems like it's a good idea to send a preamble of a bunch of edges before the data, so the receiver ATTiny can sync up. The ATTiny input pin would be edge-triggered, and the receiving code state-driven.

WAITING_STATE : hanging around waiting for edges
TIMING_STATE : got an edge, now averaging up times looking for startbit (2T)
RECEIVING_STATE : saw a startbit, now receiving data (1T=0, 2T=1)

___________   _   _   _   _   _    _   _    _    _   _   _   _    _   ____
           |_| |_| |_| |_| |_| |__| |_| |__| |__| |_| |_| |_| |__| |_|
            |                 |      |   ||   ||   |   |   |   ||   |
idle high   ^----preamble-----^ SB   0    1    1   0   0   0    1   0  idle high

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are only sending data one way then a normal UART setup should work just fine for nine devices. Of course you would still need to have an addressing scheme either way so each device knows if you're talking to it.

Mike H.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use a simple protocol:

4T = sync frame (nothing to sent)
2T = 1 bit
1T = 0 bit

The transmitter use toggle pin on compare and clear timer on compare.

The receiver works in this way, that an overflow bit means 3T was gone and the compare bit means 1.5T.
So on an external interrupt you can reset the bit counter or shift in the bits.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or manchester encode it like RC5 infrared protocol

or LIN bus.....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can program a unique address into each tiny... then do it DMX style. Use the USART, and send a break condition (Drive the TX line low for more than 1 byte period), followed by a start code, and then a stream of data packets... the destination address for each packet is its slot number after the start code.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
If you can program a unique address into each tiny... then do it DMX style. Use the USART ...

Please read the first post.
He want to use all 6 pins, so there is no way to connect a crystal for reliable UART and there is also no HW-UART inside.

But the 1T/2T approach tolerate 50% frequency error and thus the internal RC was reliable for it.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The data rate he's talking about, he could use a sufficiently low baud rate that would tolerate the inaccuracy of the internal RC. (note I said DMX like, I was not implying to use DMX exactly at the 250Kbaud that it would normally run at) Though I'll give you the lack of a HW UART as a good reason (though a software RX-only one is fairly easy)

Manchester is a better option in my opinion. This would be a little easier than your 1T/2T system, I think. With Manchester the data rate remains constant, and deterministic. Clock recovery is relatively easy too, and allows for significant drift. So unless the RC of the tinys are way off the mark (more than 25% from the transmitter) it should work fine.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suppose I could uniquely code each Tiny, though it's somewhat of a hassle doing a unique flash for each. Since they'll be SMD, I'll have to flash them before installation - remember, there are 9 of them per board.

Since 5 of the 6 pins are directly in use driving LEDs, I can't use ISP to program/update them after installation. That means coming up with an application loader, kind of a bootloader that is part of the application since there is no boot partition. The main AVR would send a UPDATE_FLASH command followed by the new flash contents.

Hrm, have to figure out how to handle that in C (Codevision). Hrm yuck, this won't be easy. When the main "app" received an UPDATE_FLASH command, it would jump to the update procedure. This would be at the start of flash I suppose, and would have to contain the IRQ(s) to handle data reception, along with a jump table into all the routines in the main portion of the app. The main app would have to live a little further up at a known location.

Hrm again, how to get CV to generate a relocatable object file. Or at least one with the equivalent of .org ...

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

perhaps you could determine address electrically. you might be able to bias some of the I/O's with resistors to generate teh ID. The resistor values will need to be quite high, so they don't illuminate any LED's (though you might get a dim glow in a dark room). I'll admit, I've never tried this on a charlieplexed array, so I have no idea if it will work.

Of course if you stick with the t12, you get EEPROM, a great place for those pesky unique ID's.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
The data rate he's talking about, he could use a sufficiently low baud rate that would tolerate the inaccuracy of the internal RC.

No !

The error was exact the same on low baudrates.

The only difference, on high baudrates the error increases further by delay times, e.g. slew rate of driver circuits, delay of opto couplers, cable capacity and so on.

The error must always be low enough, that the 9th bit was still sampled correctly.

glitch wrote:
Manchester is a better option in my opinion. This would be a little easier than your 1T/2T system, I think.

Manchester was also my first thinking on my 1-wire project. But then I found it to complicated and the 1T/2T was significant easier and less CPU load.

Further this method was independent from the polarity, because the time count from one edge to the next.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SDCC, the model train protocol, might be considered for communications. It is a unidirectional (when driving multiple receivers) serial protocol based upon narrow and wide pulses. It gives you a standard to work from. This system even routes power down the same wire.

Your design problem seems to be that you are trying to do too much with one part. Since that part is cheap, might you consider using two on each 9 LED block? The first could support more sophisticated communications on a 1-wire net and the second, not needing addressing, would then support a simple protocol controlling multiplexing. The display wouldn't be affected by communications chatter and debuggin the programs would be fairly easy. You even have pins left over to wire in address IDs.

"It's easier to ask forgiveness than it is to get permission" - Admiral "Amazing" Grace Hopper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you really think it's too much for one part ? The charlie-plexing scheme is actually pretty simple - there are two ways to do it depending on whether you use current limiting resistors on each IO pin or not. We use 5 pins to drive 9 bicolor LEDs (18 total)

1) Using resistors. No PWM needed, so it's just a matter of cycling through the pins fast enough. Say we want 100Hz to be SURE there's no flicker - then we need to cycle through each of the 5 pins at 500Hz. Set each one LOW/0 and set the others HI/1 as needed to light up the LEDs on that pin. Then move to the next.

This can be done in a simple endless main loop, leaving all the IRQs and timers available for any data transfers. At 4MHz this would spin through the loop very very fast - much quicker than 500Hz :) That 500Hz requirement would let the Tiny be clocked quite slow to help on battery usage, though the LED current will kind of overshadow whatever the Tiny uses.

2) No resistors - have to PWM to limit current to LEDs. Using the same 100Hz rate we have to visit each pin at 500Hz. Then divide this up into (say) 10 timeslots, so we're visiting each pin at 5kHz. Lowest level is with LED on for 1 timeslot out of 10, brightest (perhaps a friode) when it's on 10 out 10 timeslots. Might need more timeslots to really limit the current - I don't know yet, still need to wire one up and code it. The port pin current limits will help here.

5kHz is nothing, let alone 500Hz. There should be plenty of time left over for handling comms. Again, this can be done in a main loop, leaving IRQs and timers free if needed.

Remember, there will be 9 sets of this. Each Tiny handling 9 bocolor LEDs, 81 bicolors on the whole board, for 162 LEDs in total. And the board layout is tight :( NixieDoku partial layout

While I can probably get away with just getting the Tiny code RIGHT before commiting to hardware, it would be nice to have an update capability available, just in case :oops: I still need the 1-wire type protocol to get the which-LEDs-to-light information across to the Tinys, so may as well build the flash-update capability in there.

Probabaly can't fit it all in a Tiny25 ($1.16) but almost surely into a Tiny45 ($2.02) and most definitely into a Tiny85 ($2.62). If it's just charlie-plexing code and data-reception, then it probably will fit into a Tiny25, I'm just doubtful about fitting self-reprogramming in there too.

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean,

I wasn't refering to the ATtiny25 being computationally bound. The original question was about a 1-wire interface because your design was pin resource limited.

Before I forget, multiplexing doesn't limit the peak current in the LEDs. Cutting down on-time will reduce average current, but the ATTiny wasn't designed to tolerate high current density. LEDs are diodes. Forward current increases exponentially with forward voltage so the peak current limit will be what the active pull up and pull down transistors provide. If you encounter a bug, you might just find the circuitry trying to drive three LEDs DC. Can the device tolerate that?

To solve the original problem of getting each device to have a unique ID you have to have a clever circuit (haven't seen any suggested), or find a way to get more pins. That suggests either a pair of ATTiny25's (if you want to stay with the part for some reason), or another uC.

Your suggestion of the ATtiny24 is a more attractive solution in that it is not only cheaper than two 25s, it comes in a 14SOIC package, so you get enough pins to set unique ID and you can program and debug in situ. (Given the original posting constraints, this seems somehow like cheating.)

Have fun.

"It's easier to ask forgiveness than it is to get permission" - Admiral "Amazing" Grace Hopper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, I saw the Tiny24 is now finally available at Digikey for $1.34 soic, the Tiny44 for $1.82. Having two pins for data transmission would certainly make things easier. Still stuck with the updating via self-programming though.

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Could you amplify that last statement? I'm not sure I follow your thinking.

Here's my count -
4 pins for programming and debug
5 pins mux circuit
1 pin for 1-wire comm

That leaves two pins up for grabs. Use one pin with a resistor pair selected to give a voltage division that corresponds to an address. One pin left over to add a feature!

I might point out that SDCC is a "1-wire" scheme for supplying control and power to model rail-roads using variable width, pulsed 12V power. This could cut down on wiring at the expense of adding a regulator and a few more minor components on each module. It also gives you a well defined command and control protocol. Included in that protocol is a command for setting device address. This is done with only one module on line at a time. Just a thought.

"It's easier to ask forgiveness than it is to get permission" - Admiral "Amazing" Grace Hopper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Umm, how about ignore that last statement ? I only took the first step in seeing that the 14-pin device would enable an easier-to-use 2 or 3-pin interface for date xfer. Totally overlooked the fact that there were now enough to be able to dedicate the ISP pins to ISP.

Upside : No nasty self-programming details to work out.

Downside : Need a jig or other adapter to connect to in order to program the Tiny. 9 of them. Updates would be a pain - connect to Tiny#1, program, connect to Tiny#2, program .... Would be much easier to send the new object image to the main AVR and let it send it out to the Tinys.

Hrm - wonder if the main AVR could do the ISP programming of the Tinys ? That should be a lot easier than having them do self-programming. I'm 99% convinced to switch to a Tiny24/44 for LED handlers.

OK, off to read up on how to build an ISP. Would it be possible to gang-program all 9 Tinys at once ?

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I'll forget the last statement. I belong to the shoot first and ask questions later club anyway. ;-)

According to the data sheet, the ATTiny24 supports page erase and self programming of FLASH memory. So, what you need now is a boot loader, and as several of the Tinys have been out for a while, I imagine someone can point you to code you can adapt to your needs. Getting each part to self program individually, or even all in parallel shouldn't be too difficult.

PM me. I would like to follow you on this.

"It's easier to ask forgiveness than it is to get permission" - Admiral "Amazing" Grace Hopper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This thread has kind of morphed a little. Originally I was just looking for pointers on how to implement a 1-wire type protocol to transfer data from a main AVR to a Tiny. Simple enough - there are several schemes around, from the 1T/2T type to manchester encoding and so on.

I think I'll go with a 1T/2T type scheme. I have it more or less blocked out in my head ... First, use the preamble portion to build an average of the bit time count. Then after seeing a start bit (0 level for more than 1.5 bit-times) start looking at the edge time counts : if an edge is less than 1.5 bittime/counts it's a 0, if it's greater than 1.5 it's a 1. From there on it's a matter of protocol - how many bits in a command and so on. Fairly basic stuff.

Then the question of how to self-update the Tiny comes up. Actually getting the flash image TO the Tiny isn't that hard, it's how to save it, write it to flash and transfer control to the new image that's a bit niggly. There's another thread discussing this very problem : Tiny45 Bootloader. This is one method I have under consideration. Also have to figure out how to get CodeVision to spit out only the main portion of the Tiny app. Don't want/need all the startup code, the IRQ vectors etc. Just code starting at a given flash location, same as using .org in assembler. May wind up having to just take the asm source that CV generates, editing it down to remove all the extraneous stuff and adding in specific locator .org statements etc.

Finally, moving to a Tiny24/44 allows more pins, so ISP becomes possible : this is the other method under consideration, and the best one I think. Either plain old ISP with an off-project device (STK500, AVRISP, whatever), or best using the main application AVR to be the ISP. So run SCK/MOSI/MISO and RESET-CTL from the main AVR to all 9 Tinys I suppose. Ideal would be to gang-program all 9 Tiny44s at once.

Does anyone know if that's possible ?

Now I have to learn how to twiddle SPI to actually flash the Tinys ...

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

ISP with an off-project device (STK500, AVRISP, whatever), or best using the main application AVR to be the ISP. So run SCK/MOSI/MISO and RESET-CTL from the main AVR to all 9 Tinys I suppose. Ideal would be to gang-program all 9 Tiny44s at once.

This would be possible if you were to do it blind with no response from the slaves.( AFAIK you would need to run a separate line for MISO from each slave in order to get individual responses.) I think your original idea of using a bootloader makes the most sense here. It should be fairly easy to implement in a small space. If you need something small in asm I would be happy to lend some code.

Mike H.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mike - thanks for the offer, I'll definitely take a look at whatever you have. It's not so much a bootloader that I would need as it is an application updater. I think that's going to tough (but definitely possible) to do for a couple of reasons ...

How to update code-in-place ? I think dividing flash into 3 "partitions", one active, one for updates, and the start of flash for the IRQ vectors and a jumptable for all routines would do it. While receiving an update, the app would write it to the standby partition, when complete would copy the jumptable from the update to the current jumptable and update the IRQ vectors. Then jump into the new code.

Icky. Tricky to generate the correct update-image as well, unless doing it in pure assembler. While I can do small stuff and optimization etc in assembler, I'm really a C kinda guy (Codevision). The Tiny45 Bootloader I mentioned above should be interesting.

Dean 94TT
"Life is just one damn thing after another" Elbert Hubbard (1856 - 1915)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If your comm scheme will not require any interrupts then things will be easy. You would keep your bootloader along with the comm code at the end of flash and the rest is fair game. Just wait for a unique character seq to initiate the bootloader, jump to the bootloader section, the bootloader will update the app program on the fly, when finished just jump to 0 and the new app will start.

Mike H.