UART interrupts

How do I enable the Rx interrupt on the Arduino?

What I'm doing right now is I have a SeeedStudio flow sensor attached to Int0 on an ATMEGA328, every time the sensor output goes "high" I increment a counter, this is my "Barnduino".

On my Arduino Mega I have a DS1307, (amongst other things!), I've enabled the 1hz square wave output on the DS1307 and have it connected to Int18, so every second I increment a counter, every 60 seconds I send an "F" to my "Barnduino", which sends back how many pulses the flow sensor has produced, then every 10 minutes I wake up an SHT15 temperature/humidity, take a reading, if it's below the current minimum or maximum recorded value the latest value replaces either the min or max value, once an hour I write the min/max temperature, humidity and how many pulses the "Barnduino" has recorded from it's flow sensor to a bank of 24LC254 EEPROMS.

Once a week we get the data, send it off to management and clear the storage.

What I want to do is when the "Barnduino" senses "abnormal" water flow, it will send an "A", for an alarm state, to my Mega.
Most of the time the Mega is just sitting there waiting for the next interrupt from the DS1307 or a keypress.

The longest the "Barnduino" can go without having it's flow count queried is 60 seconds, which is fine.
I thought it might be an elegant addition to have the Mega's UART RX interrupt in play, just for the hell of it.

Reading the ATMEGA data sheets I know it's possible.

And yes, I realise this is overkill, but it might come in handy to know for something else.

The Serial object (and also Serial2, 3 and 4 on the Mega) use the Receive interrupt to put the characters into a ring buffer... to get them is easy..

The Serial objects are well documented in the Reference section...

This code is as simple as i could make it.... assuming you use the 2nd Uart...

void setup()
{
    Serial2.begin(9600); // use this port and speed for device 
}

void loop()
{
    char in_byte ;
    if (Serial2.available())
        in_byte =  Serial2.read() ;
}

That is how I use all 4 UART's on my Mega's now.

In the ATMega1280 reference, Section 13, Interrupts, Page 105,

Table 13-1. Reset and Interrupt Vectors

Vector# Address Source Definition
26 $0032 USART0 RX USART0 Rx Complete
37 $0048 USART1 RX USART1 Rx Complete
52 $0066 USART2 RX USART2 Rx Complete
55 $006C USART3 RX USART3 Rx Complete

On microprocessors I've used in the past, I'd point the interrupt vector to a routine to poll all the devices status registers to see which one generated the interrupt.

The reason I'd like to try out an Rx register full interrupt is I'm going to multiplex 8 serial devices on 1 Mega UART, simply diode OR them together.
When I get an "A" or alarm condition code from one of my "Barnduino's" I'm going to poll them one at a time to see which one triggered the event.
The point here is this is mission critical stuff, small creatures depending on my software/hardware, so I'm going to go to great lengths to prevent single point failure.
If I can't do this from the Arduino environment I'll have to to it in assembler.

What is a 'barnduino'?

if you look in the install directory under "hardware/arduino/cores/arduino" you should find HardwareSerial.cpp and HardwareSerial.h.

The interrupt functions are in the .cpp :).

The fourth UART (or Serial 3)

SIGNAL(SIG_USART3_RECV)
{
  unsigned char c = UDR3;
  store_char(c, &rx_buffer3);
}

As you can see no need for assembler :slight_smile:

But I think there might be need for more system design before you leap in.

If two devices try to send an 'A' on a serial port at overlapping times using simple hardware ( eg diode or-ing or open collector or ..) then some of the edge transitions for the bits can be confused - I am 99.99% certain that the device could see corrupted data and not see the 'A'.

This is not a guaranteed way to signal for attention - which your message said you required.

Perhaps you should consider using a BREAK to signal the interrupt?

This would also need proper hardware design (not my strong point) but it is the more usual approach I believe.

Then you can poll using an address sent to each device to indicate they can individually communicate their need for attention in a time slot starting after the poll.

Is this the approach you had in mind?

If so.. I think you could modify the interrupt handler to capture the errors and pass them through.

This code crams the error signals into the high bit of the byte - and keeps the rest of the interface unchanged.

SIGNAL(SIG_USART3_RECV)
{
  unsigned char e = UCSR3A; // read the error flags associated with the byte in UDR3
  unsigned char c = UDR3;

// this code is broken out for reading
  if (e & FE3) // framing error, i.e. break
     store_char(c|0x80,  &rx_buffer3);

  else if (e & DOR3) // Data overrun
     store_char(c|0x80,  &rx_buffer3);

  else if (e & UPE3) // parity error. This should not happen unless you change the UART settings to enable parity generation and checks.
     store_char(c|0x80,  &rx_buffer3);

  else
     store_char(c, &rx_buffer3);
}
   // is the same as the three tests above
   if (e & (FE3 | DOR3 | UPE3)) // if any error code is set
     store_char(c|0x80,  &rx_buffer3);

in your normal code, that is still very fast relative to serial communications, you can deal with the bytes in the normal way.

loop()
{
   if (Serial3.available())
   {
      char c = Serial3.read();
       if (c & 0x80)
            check_for_interrupt_request() ;
       else
            normal_character(c) ;
    }
}

When I get an "A" or alarm condition code from one of my "Barnduino's" I'm going to poll them one at a time to see which one triggered the event.

Much simpler to have each Barnduino send a different alarm condition. The 1st on sends A1. The 2nd sends A2. And, so on.

No polling (and no additional code needed on the Barduino) to determine which one reported the problem.

I was going to use MAX232's to send the serial data from the barnduino's back to the Mega.
You get 4 lots of RS232 level, I was thinking when I walked the dog just then I will use a 4 lines.
Rx
Tx
Alarm
Busy

When a Barnduino detects a possible leak, it will assert the Alarm line, I'll diode OR the Alarm lines to the Busy lines.
That way I can use an External Interrupt on the Mega.

I like some of the suggestions posted so far here, I can see a LOT of false alarms before I figure out the difference between heavy drinker use and a legitimate water leak.

What's the best way to get circuit diagrams here?
As I've said on quite a few posts, I REALLY like building stuff from 7400 series chips!

By the way a Barnduino is an ATMEGA328 on a prototyping board, it's got a MAX232, a 7805 voltage regulator, a "think" LED (pin 13) and an LED on the output of the flow sensor.
I put a couple together today and tried them.

Having 8 devices transmiting whenever they like is a recipe for corruption, and if some of them are almost in sync it will take ages to recover.

As we're talking very slow timings here I would simply poll the Barnduinos, that way there is (almost) no chance of a stuff up. It's a simple

<1>
<2>
<3>
etc.

Any system that allow asynchronous access to the "network" will need a lot more work.

RS-232 may not be the best medium, it depends on the distances involved, but also you can't tristate 232 drivers. RS-485 can be tristated (so no diodes needed) and doesn't need 4 caps per driver (although some MAX2x2 chips don't as well). However if your boards already have 232 drivers then fair enough.


Rob

Graynomad:
Having 8 devices transmiting whenever they like is a recipe for corruption, and if some of them are almost in sync it will take ages to recover.
RS-232 may not be the best medium, it depends on the distances involved, but also you can't tristate 232 drivers. RS-485 can be tristated (so no diodes needed) and doesn't need 4 caps per driver (although some MAX2x2 chips don't as well). However if your boards already have 232 drivers then fair enough.
Rob

I only went RS-232 cos' I already had a rail of MAX232's.
I was planning on polling them, it was only in the event of an alarm event.

Diode OR ing RS232 devices works well, when you add flow control it works even better!
As an example, ages ago I scored 20 Data General terminals, for a party we ran the cheapest 3 core cable we could find around the house, just had GND, Rx and Tx.
All of the terminals were diode OR'd together, even with 20 "slightly tipsy" :slight_smile: fools bangin away on all the keyboards it worked great!
Flow control was handled by "eye" and excess beer!

The other reason I'm using RS232 is these barns are electrically very noisy, there are single and 3 phase motors, as well as a 4KV fence zapper, anti perch line on all the feed and water lines.

The "Barnduino's" are there pretty much just to read the flow sensor and later on turn off a solenoid valve.
There was no possible way I was going to be able to run TTL levels any kind of distance in the sheds.
We have 2 barns, one is 300' long, the other is 360' long.
Here's "my office"! :slight_smile:

The water lines that I'll be monitoring are split in 2 sections, lengthwise in the sheds.
The longer shed has 4 sections, the "smaller" shed has 8.

My plan is to diode OR all the Barndiuno Tx outputs into a single Mega UART Rx input, then multiplex a Mega Tx line, probably with a 74LS138.
That is how I was going to poll each Barnduino.
I just thought it would be cool to get the Barnduino's to signal an alarm condition!

So how do I get circuit diagrams here? What is the best format?
It would be a lot easier to show you guys the circuit, a picture is worth a thousand words!
Especially when it's a circuit diagram!

Flow control was handled by "eye" and excess beer!

That's funny, whenever I have excess beer I have much less control over any flow.

The other reason I'm using RS232 is these barns are electrically very noisy,

More reason to use RS-485. Nice office BTW, bit different from those I've occupied over the years.

I just thought it would be cool to get the Barnduino's to signal an alarm condition!

Fair enough, it does add complexity though and if you're polling fast enough the end result is the same. After all if you get the alarm within a second or two that would be plenty fast enough I would think as it's for detecting leaks I gather.

As for detecting leaks vs heavy drinkers, that might be a challenge. Why would some birds drink more than others?

one is 300' long, the other is 360' long.

IIRC that's longer that 232 is spec'd for.

I REALLY like building stuff from 7400 series chips!

Are you a masochist or what :slight_smile:

So how do I get circuit diagrams here? What is the best format?

For my money PDF, everyone has a PDF reader. Alternateively a PNG/JPG. Please no special schematic formats.

a picture is worth a thousand words!

Even more probably, please post the circuit.


Rob

THAT.............IS A WHOLE LOT OF TURKEYS

Use RS-485 drivers and receivers. They reject common mode noise wonderfully. We used them in a oil refinery (3 phase power everywhere), often runs of several thousand feet at 9600 baud.

And yes, pole the slaves, ask for alarm status, don't turn your project into a turkey. Did I really say that? .....Sorry. XD

That video is when there were only toms left in the barn!
We have around 20,000 birds between both sheds!

Can you recommend an RS-485 transceiver IC?

Like I said I have a rail of MAX232's, I got a good price on 100, 20 years ago when they were still AUS$12 each!
Been whittling down my stock over the years!

I won't be running RS-232 down the length of the shed, just across.
A big problem here is power, every damn job is at least 3 extension leads just to run a drill or soldering iron or what ever.
I am going to get a little, cheap ass GMC 450W generator just to run power tools.

My main Mega will be in the control rooms, at the southern end of the sheds I'm going to put up some photovoltaic panels an a little S rotor for power.
I'll put another Mega/XBee node there.

I'm really getting into this XBee thing, they are great!
Just "out of the box" it's like having a serial cable"
I had thought of pairing each Barnduino with an XBee module, but that bought the cost up to nearly AUS$200/node and is a little too much overkill even for me!

I bought a copy of "Making Things Talk" by Tom Igoe and a copy of "Programming Interactivity" by Joshua Noble, both books are GREAT!
I've gotten a lot of ideas from both of them.

Once I get this water usage monitor up and running I'm going to have a crack at getting a silo level monitor happening.
That will be a sonar system, 1 Tx, with 3 Rx units, that way I'll not have to worry about the feed level being a cone shape.
I've messed around with "synthetic aperture" sonar for a while now and even with a 1MHz 6502 I have had some good results.

And yes I am a masochist! I still hand assemble 6502 code!

6502! OMG :astonished:

Can you recommend an RS-485 transceiver IC?

LTC1487
LT1785
LT1791

MAX13414, integrated 5v regulator and auto direction control so you don't have to control the Tx.

I must say this sounds like an interesting project.


Rob

Thanks!

It's something I have to do, I have had enough shovelling and lugging sawdust around.
I had health issues before I decided to have a "tree change", since I've been here I've moved literally 100's of cubic metres of sawdust and shavings.
All that needs to happen is a damn crow flies past, the birds freak, knock a drinker cup off the line and I'm cleaning up for hours, sometimes days.
Worst is when fox's freak them out at night and the water runss for hours.
If I can catch a drinker "oopsie" in the first few minutes it's a lot easier than after the birds have emptied the whole 2000 litre header tank into the shed and the water and "flup" is over the tops of my rubber boots.

The other thing this system will deal with is management wants us to log mi/max temperatures, so I'll give them humidity as well.

Just got Processing to work under Ubuntu netbook remix, so I'm sitting here in the heat writing some code to plot hourly temperatures.

Sure is hot today and windy.
Every time I think I smell smoke my heart skips a few beats.