Show Posts
Pages: [1]
1  Topics / Home Automation and Networked Objects / RFC for Arduino Control Bus (ACB) on: June 17, 2013, 06:16:16 am
After searching for a while I found that MODBUS is a good system. But it is not perfect for arduino, so I decided to create a new protocol called it Arduino Control Bus or ACB which work similar to MODBUS. The system communicate via RS485 with ASCII format only makes it easy to monitor and very cost effective. This system may be applied in various projects such as Building Automation System, Process Controller or just simple household monitoring etc.

The protocol for both MASTER/SLAVE as followings

MASTER
Code:
Control Bus is fixed length(depend on ptype or arduino board) communication via RS485 using ASCII only.
Packet format (MASTER) for UNO, Duemilanove type 0 or 1
- start byte using *
- slave id use 3 bytes
- ptype use 3 bytes
- digital data use 11 bytes, each byte will be 1 or 0(zero) in ASCII, ignore data when READ
- end byte using ;
sample data :
*00100011111111111; = (ptype = 0)read all analog and digital from slave number 1
*00100000000000000; = (ptype = 0)read all analog and digital from slave number 1
(last 11 digits before ; are ignored because READ only)
*00100111111111111; = (ptype = 1)read all analog and set all digital pins to HIGH from slave number 1
(DO NOT recommend to use digital pin 13 for read and write if connect to LED on board)
TERM of variable :
PTYPE is type of devices that may be different depend on type of arduino board and how to use pins on each board.
ptype 0 - 100 are reserved for UNO or Duemilanove and 101 - 255 for MEGA or DUE
The following are samples of ptype for UNO, Duemilanove
type 0 = all analog and digital pins are for READ
type 1 = all analog pins for READ and all digital pins for WRITE
...
type 51 - 100 reserved for custom type
The following are samples of ptype for DUE, MEGA
type 101 = all analog and digital pins are for READ
type 102 = all analog pins for READ and all digital pins for WRITE
...
type 201 - 255 reserved for custom type
ID is device number for a slave which can be 1-999 and number 0(zero) reserve for broadcasting only.
***DO NOT BROADCAST when you need response from slaves because only one device can response at a time***
***BROADCASTING will be silence WRITE (write without response therefore you need to query again to make sure everything OK)***
BAUD is speed in bps(bit per second) for communication, default is 19200.
enablePin is the pin that toggle communication between send and receive (default is 2).

SLAVE
Code:
Control Bus is fixed length(depend on ptype or arduino board) communication via RS485 using ASCII only.
Packet format (SLAVE) for UNO, Duemilanove type 0 or 1
- start byte using -
- slave id use 3 bytes
- ptype use 3 bytes
- analog use 18 bytes, each pin use 3 bytes total 6 pins
- digital data use 11 bytes, each byte will be 1 or 0(zero) in ASCII, ignore data when READ
- end byte using ;
sample data :
-00100011122210120212309910101010101; -> read all analog and digital from slave number 1
-00100111122210120212309911111111111; -> read all analog and set all digital pins to HIGH from slave number 1
(DO NOT recommend to use digital pin 13 for read and write if connect to internal LED)

This protocol is designed as simple as possible, hopefully it will be useful for someone who plan to implement central(local or even remote) control system.

more details at http://www.thainetbeans.com/arduino/acb/acb.php

any suggestion is welcome.

Thanks
2  Using Arduino / Programming Questions / Re: Serial Master/Slave problem using serialEvent on: June 04, 2013, 04:16:48 am
Problem solved!

Thanks
3  Using Arduino / Programming Questions / Serial Master/Slave problem using serialEvent on: June 04, 2013, 02:34:56 am
I've made Master/Slave via RS485 using serialEvent.

Here is the code for Master :

Code:
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
String poll = "*00100011110001111;";
int i = 0;

void setup() {
  // initialize serial:
  Serial.begin(19200);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);  
  pinMode(2, OUTPUT);
}

void loop() {
  poll.setCharAt(1, 'a' + i++);
  if(i > 10) i = 0;
  digitalWrite(2, 1);
  delay(1);
  Serial.println(poll);
  waiting();
  digitalWrite(2, 0);
  delay(1);
  response();
  delay(1000);
}

void response() {
  if (stringComplete) {
    Serial.println(inputString);   // echo response from slave device
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    
    if(inChar == '-')
      inputString = "-";
    else
      inputString += inChar;
    // if the incoming character is a ";", set a flag
    // so the main loop can do something about it:
    if (inChar == ';') {
      stringComplete = true;
    }
  }
}


void waiting() {
  while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
    UCSR0A |= 1 << TXC0;  // mark transmission not complete
  while (!(UCSR0A & (1 << TXC0)));   // Wait for the transmission to complete
}


Here is the code for Slave :

Code:
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

void setup() {
  // initialize serial:
  Serial.begin(19200);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
  pinMode(3, OUTPUT);    // enable pin for rs485
  digitalWrite(3, 0);
  delay(1);
}

void loop() {
  if (stringComplete) {    
    digitalWrite(3, 1);    // enable send
    delay(1);
    Serial.print(inputString);
    waiting();
    digitalWrite(3, 0);    // enable receive
    delay(1);
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    
    if(inChar == '*')
      inputString = "-";
    else
      inputString += inChar;
    // if the incoming character is a ";", set a flag
    // so the main loop can do something about it:
    if (inChar == ';') {
      inputString = inputString.substring(0, 7) + "111222333444555666"
                    + inputString.substring(7);
      stringComplete = true;
    }
  }
}

void waiting() {    
  while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
    UCSR0A |= 1 << TXC0;  // mark transmission not complete
  while (!(UCSR0A & (1 << TXC0)));   // Wait for the transmission to complete
}

The message between Master and Slave is attached, Master start with "*" and Slave start with "-"

The problem is Master always get lack of response from Slave one step,
actually it is acceptable but I wonder if there is a way to make it better,
I knew that serialEvent only work after loop but do not have idea how to solve this.
Any idea is welcome.

Thanks in advance,
4  Using Arduino / Microcontrollers / Re: ATMega 328P-PU on Breadboard with PL2303 USB>Serial on: December 17, 2012, 03:45:50 am
The following link show how to auto upload, but I have no luck with that.


http://www.xappsoftware.com/wordpress/2012/04/16/how-to-upload-sketches-to-arduino-uno-chip-using-pl2303-usb-to-rs-232-converter/
5  Using Arduino / Microcontrollers / Re: How to program using USBASP and keep bootloader on: October 16, 2012, 03:57:45 am
It sounds as though the wdt_disable call isn't working and the wdt_enable call is setting the wrong timeout. This is the code I use to disable the watchdog:

Code:
  // Turn off watchdog timer
  cli();
  wdt_reset();
  MCUSR = 0;    // clear watchdog reset flag
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = 0x00;
  sei();



Thanks you so much, it works like a charm.
6  Using Arduino / Microcontrollers / Re: How to program using USBASP and keep bootloader on: October 15, 2012, 09:24:52 am
I have tested 4 atmega328 chips with various delay values and I found that
watchdog stopped working when used delay value between 17 - 18.
(2 chips fail when use delay(17) and the others fail when use delay(18))
here is my code.

Code:
#include <avr/wdt.h>

void setup()
{
  wdt_reset();
  wdt_disable();
  pinMode(13, OUTPUT);
//  digitalWrite(13, HIGH);   
//  delay(100);             
//  digitalWrite(13, LOW);   
  delay(16);  // watchdog stop working when delay between 17 - 18
  wdt_enable(WDTO_4S);
  wdt_reset();
}

void loop()
{
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);   // set the LED off
  delay(1000);              // wait for a second       
  wdt_reset();
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);   // set the LED off
  delay(1000);              // wait for a second         
  wdt_reset();
  digitalWrite(13, HIGH);   // set the LED on
  delay(5000);              // wait for 5 second to test watchdog
  wdt_reset();
}

BTW there was no problem even included liquidcrystal library and initialized it.
For safety, operating time in setup function shall not longer than 15 ms for watchdog to work properly.
Hope this will help someone who have same problem as mine.
7  Using Arduino / Microcontrollers / Re: How to program using USBASP and keep bootloader on: October 13, 2012, 05:12:58 am
Atmel recommends that you always reset the watchdog before disabling it. Possibly the wdt_disable function does this already, but try inserting a call to wdt_reset before the call to wdt_disable, in case it doesn't.

Still no luck even if I did that, thank you anyway.
8  Using Arduino / Storage / Re: Question about EEPROM on: October 13, 2012, 12:18:42 am
Thanks you so much for the response,
I need to know this in order to evaluate lifetime of my project.
Another question I would like to know is
What is the normal lifetime of an arduino board?
I means if I use it in normal condition, will it work for 3-5 years?
9  Using Arduino / Microcontrollers / Re: How to program using USBASP and keep bootloader on: October 12, 2012, 11:51:24 pm
As johnwasser says, you don't need the bootloader to use the watchdog timer. HOWEVER, there is a problem you may have run into that the bootloader "solves". The problem is that when the watchdog timer expires and causes a reset, the watchdog is still enabled. The processor needs to complete the data initialization that occurs before setup() is called, before the timer expires again. Otherwise the watchdog will cause another reset, and this will repeat so that your sketch never gets the chance to reset the timer. The bootloader "solves" this by disabling the watchdog.

So it comes down to what you have in your sketch whose static initialization takes longer than the watchdog interval. The usual culprit is the LiquidCrystal library, which has a totally unnecessary "begin" call in its constructor, taking 60ms to execute (longer than the longest available watchdog interval). If you are using the LiquidCrystal library in your sketch, you need to remove this call from the LiquidCrystal library source code, otherwise you can't use the watchdog timer.

Your answer make me clear, Thanks you so much.
Anyway I think there will be no watchdog interval left if it start working (it start because it reach the interval, am I right?),
In this case, what is the longest time left for me to use?
The problem is I need time not only for liquidcrystal but eeprom initializing as well.
10  Using Arduino / Microcontrollers / Re: How to program using USBASP and keep bootloader on: October 12, 2012, 11:34:30 pm
Thanks, I finally find that without bootloader watchdog still work.
Anyway please see what worng with my code that causes watchdog stop working.
I know that it will work if I just comment out blink led in setup,
but I do not know why.

Code:
#include <avr/wdt.h>

void setup()
{
  wdt_disable();
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);   // without this line, work fine
  delay(100);                      // without this line, work fine
  digitalWrite(13, LOW);    // without this line, work fine
  delay(100);                      // without this line, work fine
  wdt_enable(WDTO_4S);
  wdt_reset();
}

void loop()
{
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);   // set the LED off
  delay(1000);              // wait for a second       
  wdt_reset();
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);   // set the LED off
  delay(1000);              // wait for a second         
  wdt_reset();
  digitalWrite(13, HIGH);   // set the LED on
  delay(5000);              // wait for 5 second to test watchdog
  wdt_reset();
}
11  Using Arduino / Storage / Question about EEPROM on: October 12, 2012, 12:05:07 pm
I use eeprom in Atmega chip to record some data and I wonder what will happen after reach eeprom's life,
the chip still work but can not record any data or the chip just stop working?

Thanks in advance,
12  Using Arduino / Microcontrollers / How to program using USBASP and keep bootloader on: October 12, 2012, 11:08:18 am
Hi,
I am a newbie, I try to upload program using usbasp and it works fine
unfortunately I find that my arduino become no bootloader.
The problem is without bootloader, watchdog does not work.
I use barbone arduino board with atmega328.

Please let me know, how to program using usbasp and still keep bootloader.

Thanks in advance,
Pages: [1]