Arduino Board Diagnostics

Hi,

Is it possible to ascertain various bits of system information, programmatically, such as Board Type & Revision, Available Memories etc.

Thanks,
jB

I would think some of that info would have to be programmed into EEPROM: board type & revision, as many boards use the same processor. '328s are in all kinds of things for example.
Available memories could be looked up knowing the processor type, reading the Signature Bytes would provide that.
Etc. might refer to bootloader installed? Sketch being run? More definition needed.

Hi CrossRoads,

Thank you for your reply.
I am attempting to obtain information about the Arduino Boards for a project.
I think the first step is to look as you said at the signature bytes to ascertain the Atmel chip type.
Now as I am new to Arduino but am an old dog that has to take up c and c++ again to achieve my project, could you please give me a pointer (no pun intended) as to how to retrive the signature bytes?

Appreciate your help.
Kind reagrds,

jB

From the '328 datasheet:

27.8.10 Reading the Signature Row from Software
To read the Signature Row from software, load the Z-pointer with the signature byte address
given in Table 27-5 on page 289 and set the SIGRD and SPMEN bits in SPMCSR. When an
LPM instruction is executed within three CPU cycles after the SIGRD and SPMEN bits are set in
SPMCSR, the signature byte value will be loaded in the destination register. The SIGRD and
SPMEN bits will auto-clear upon completion of reading the Signature Row Lock bits or if no LPM
instruction is executed within three CPU cycles. When SIGRD and SPMEN are cleared, LPM will
work as described in the Instruction set Manual.

I am totally not sure what all that means - but the IDE can read the bytes during a serial download, so its gotta be doable.

yea its avrdude responding in the IDE's case

Its obviously doable, you just got to poke the right registers, I kind of want to know "why" though, your typical arduino is a mega 8, 168 or 328 which are more or less the same deal

Hi,

The answer as to why is "is it possible and how"?

If the project I am doing is viable I would like to be able to interrogate the systems remotely seeing what board is in use, what my firmware is etc.
Now I could obviously encode into the eeprom various bits of info but if something is there already I would rather not re-invent the wheel.

I also suppose that ultimately it would be nice to have a diagnostics library able to return information much like diagnostic tools on Linux & Windows do.

To me it's a bit like why invent the light bulb when we have candles? It's just a logical step of data acquisition.

Really appreciate though any help in making a diagnostics library.

Kind regards,

jB 8)

Inspired by CrossRoads:

#include <avr/boot.h>

#define SIGRD 5

void setup ()
{
Serial.begin (115200);
Serial.println ();

byte sig;
  sig = boot_signature_byte_get (0);
  Serial.println (sig, HEX);

  sig = boot_signature_byte_get (2);
  Serial.println (sig, HEX);

  sig = boot_signature_byte_get (4);
  Serial.println (sig, HEX);
}

void loop () {}

Output:

1E
95
F

Compare to avrdude output:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f

Seems to work OK.

And the fuse and lock bits:

#include <avr/boot.h>

#define SIGRD 5

void setup ()
{
Serial.begin (115200);
Serial.println ();

Serial.println ("Signature");

byte sig;
  sig = boot_signature_byte_get (0);
  Serial.println (sig, HEX);
  sig = boot_signature_byte_get (2);
  Serial.println (sig, HEX);
  sig = boot_signature_byte_get (4);
  Serial.println (sig, HEX);

Serial.println ("Fuses");
byte fuse;
  
  fuse = boot_lock_fuse_bits_get (GET_LOW_FUSE_BITS);
  Serial.println (fuse, HEX);
  fuse = boot_lock_fuse_bits_get (GET_HIGH_FUSE_BITS);
  Serial.println (fuse, HEX);
  fuse = boot_lock_fuse_bits_get (GET_EXTENDED_FUSE_BITS);
  Serial.println (fuse, HEX);
  fuse = boot_lock_fuse_bits_get (GET_LOCK_BITS);
  Serial.println (fuse, HEX);
}

void loop () {}

Output:

Signature
1E
95
F
Fuses
FF
DE
FD
CF

Compare:

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DE
avrdude: safemode: efuse reads as 5

The efuse is different but I suspect avrdude masks out the high-order bits because they are not in use.

Dang Nick, you know your stuff!
Will those commands work on any of the arduino-type uC clones?

They should because it is the same processor. Disclaimer: the signature bytes may be processor specific according to various sources. But it wouldn't hurt to try.

Hi Nick,

This is superb stuff just what I was looking for.
It would be great if we could get some sort of db going with the signature bytes xrefed against boards.
I will try on my boards and post the outcomes.

I know it probably sounds grandiose but I think it would be great to eventually end up with a diagnostic sketch, that reported on as many features as possible.
I've always enjoyed looking under the hood, and remember years ago using code from Dan Brown to create a full DOS diagnostics suite. It came in really handy when I was freelancing as a repair man as I could run my program and drill down to obvious issues rather than hunting for the elusive needle in a haystack.

Kind regards to all "Hoodies",

jB 8)

"signature bytes xrefed against boards"
Boards can be made with any chip. Easy enough to browse the datasheets and collect the signature bytes.
Here's a starting point:
3 Signature Bytes
ATmega48A 0x1E 0x92 0x05
ATmega48PA 0x1E 0x92 0x0A
ATmega88A 0x1E 0x93 0x0A
ATmega88PA 0x1E 0x93 0x0F
ATmega168A 0x1E 0x94 0x06
ATmega168PA 0x1E 0x94 0x0B
ATmega328 0x1E 0x95 0x14
ATmega328P 0x1E 0x95 0x0F

3 Signature Byte, JTAG Part Number, JTAG Manufacture ID
ATmega164PA 0x1E 0x94 0x0A, 940A 0x1F
ATmega324PA 0x1E 0x95 0x11, 9511 0x1F
ATmega644PA 0x1E 0x96 0x0A, 960A 0x1F
ATmega1284P 0x1E 0x97 0x05, 9705 0x1F
ATmega640 0x1E 0x96 0x08, 9608 0x1F
ATmega1280 0x1E 0x97 0x03, 9703 0x1F
ATmega1281 0x1E 0x97 0x04, 9704 0x1F
ATmega2560 0x1E 0x98 0x01, 9801 0x1F
ATmega2561 0x1E 0x98 0x02, 9802 0x1F

Suppose we could summarize all this and put it in a Playground page.

http://arduino.cc/playground/Main/ShowInfo

maybe?

Just tried on an Attiny85, 8Mhz

Signature
1E
93
B

reading the fuses gives this error

sketch_may03b.cpp: In function 'void setup()':
sketch_may03b:22: error: 'BLBSET' was not declared in this scope
sketch_may03b:24: error: 'BLBSET' was not declared in this scope
sketch_may03b:26: error: 'BLBSET' was not declared in this scope
sketch_may03b:28: error: 'BLBSET' was not declared in this scope

Try adding the define below to near the top of the sketch:

#define SIGRD 5
#define BLBSET 3  // <-- add this

For another approach, see:

http://arduino.cc/forum/index.php/topic,104305.0.html