Atmel UC3 - how to get the serial number? - atmel

Each Atmel UC3 apparently has a unique serial number. Does anyone know how I retrieve it in software?

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=922774&sid=8ce72b4a3a0697eaafed1ec7413c3bd3#922774
Even better: I wrote to Atmel tech support (which I should have done in the first place?) and got this reply:
The serial number is defined by a 120-bit data located at address 0x80800204-0x80800212 for UC3A. For each chip, the serial number is unique.
Here is an example:
volatile unsigned int* id_data = 0x80800204;
unsigned int ID_get[4];
for(int i=0;i<4;i++)
ID_get[i] = *id_data++;

Related

Can SPI used for shift register(serial to parallel) CD4094

I have a project like below. I am trying to send the data using SPI but the LEDS are not glowing in sending pattern.
I am new to STM32. Could anyone please let me know if SPI can be used in this scenario OR not.
STM32f207 ======> RS232 ======> CD4094 ==========> LEDS (1 to 8)
CD4094 (serial to parallel communication)
Code Snippet::
uint8_t test = 0xFF;
status = HAL_SPI_Transmit(&hspi1, (uint8_t*)&test,1,100);
Thanks,
Rajasekhar.

How to address Port names (PORTB etc) in an array (arduino uno)

Is it possible to put the names of ports in an array?
I'm looking something like:
const ??? my_ports_config[8]= { PORTB, PORTD, PORTB, PORTB, PORTD, PORTB, PORTB, PORTD };
So to do (direct register bit set):
my_ports_config[i] |= _BV(7);
Is it possible?
volatile byte* const my_ports_config[8]= { &PORTB, &PORTD, &PORTB, &PORTB, &PORTD, &PORTB, &PORTB, &PORTD };
Of course you can. The PORTB name is nothing but a handy alias, a #define for an address on the chip. Depending on the Arduino model, that can vary of course. The easiest way to learn these addresses is to study the datasheet for the microcontroller part on your device. In the Atmel documentation they're always listed late in the document in a chapter called "Register Summary." But for the Uno I think you need the 328P datasheet Check out page 615. The 328 only has ports B C and D though, so actually setting the ports directly will probably take fewer instructions.

Arduino as slave with multiple i2c addresses

I would like to use an Arduino as an i2c slave. But I require that the Arduino acts as multiple devices by registering itself with multiple i2c addresses.
This is probably not something one would normally do, but here is my reason for doing it:
I want to use an Arduino to act as Telemetry sensors for Spektrum Telemetry. The Telemetry receiver has a few i2c plugs which connects to multiple sensors (current 0x02, voltage 0x03, airspeed 0x11, etc) each that have a fixed i2c address which the Telemetry receiver expects.
I would like to use one Arduino to act as all these devices by registering itself with all of the above addresses, and responding appropriately with the readings.
I could use one Arduino per sensor, which seems silly as I can perform all these readings with one Arduino pro-mini.
I know you can register the Arduino using
Wire.begin(0x02);
But I require something similar to this (pseudo code)
Wire.begin(0x02, 0x03, 0x11);
And when a request is received, I need to know with what address the Arduino was queried.
For example (pseudo code)
void receiveEvent(byte address, int bytesReceived){
if(address == 0x02){
// Current reading
}
else if(address == 0x03){
// Voltage reading
}
else if(address == 0x11){
// Airspeed reading
}
}
Any advice would be appreciated.
It is not possible to make the Arduino listen to to multiple slave addresses by using the Wire library since Wire.begin() only allows to pass a single slave address.
Even the Atmel ATmega microcontroller on which most Arduinos are based only allows its hardware 2-wire serial interface (TWI) to be set to a single 7-bit address via its 2-wire address register TWAR. However, it is possible to work around this limitation by masking one or more address bits using the TWI address mask register TWAMR as documented (somewhat briefly) in e.g. this ATmega datasheet section 22.9.6:
The TWAMR can be loaded with a 7-bit Salve (sic!) Address mask. Each of the bits in TWAMR can mask (disable) the corresponding address bits in the TWI address Register (TWAR). If the mask bit is set to one then the address match logic ignores the compare between the incoming address bit and the corresponding bit in TWAR.
So we would first have to set up the mask bits based on all I2C addresses we want to respond to by OR'ing them and shifting right to match the TWAMR register layout (TWAMR holds mask in bit7:1, bit0 is unused):
TWAMR = (sensor1_addr | sensor2_addr | sensor3_addr) << 1;
The main problem from here on will be to find out which particular I2C address was queried (we only know it was one that matches the address mask).
If I interpret section 22.5.3 correctly, stating
The TWDR contains the address or data bytes to be transmitted, or the address or data bytes received.
we should be able to retrieve the unmasked I2C address from the TWDR register.
ATmega TWI operation is interrupt-based, more specifically, it utilizes a single interrupt vector for a plethora of different TWI events indicated by status codes in the TWSR status register.
In the TWI interrupt service routine, we'll have to
make sure the reason why we've entered the ISR is because we've been queried. This can be done by checking TWSR for status code 0xA8 (own SLA+R has been received)
decide which sensor data to send back to the master based on what I2C address was actually queried by checking the last byte on the bus in TWDR.
This part of the ISR could look something like this (untested):
if (TWSR == 0xA8) { // read request has been received
byte i2c_addr = TWDR >> 1; // retrieve address from last byte on the bus
switch (i2c_addr) {
case sensor1_addr:
// send sensor 1 reading
break;
case sensor2_addr:
// send sensor 2 reading
break;
case sensor3_addr:
// send sensor 3 reading
break;
default:
// I2C address does not match any of our sensors', ignore.
break;
}
}
Thanks for asking this interesting question!
I really do like vega8's answer, but I'd also like to mention that if your I2C master isn't going to clock things incredibly fast, using a software-based implementation of I2C would also be feasible and give you the freedom you want.
You might want to consider that approach if rough calculation shows that the time spent in the TWI ISR is too high and interrupts might start to overlap.
void setup()
{
Wire.begin(0x11 | 0x12); // Adr 11 and 12 are used for Alt and Speed by Spectrum DX
Wire.onRequest(requestEvent); // register callback function
TWAMR = (0x11 | 0x12) << 1; // set filter for given adr
}
void requestEvent() {
int adr = TWDR >> 1; // move 1 bit to align I2C adr
if (adr == 0x12) // check for altitude request at adr 12
Wire.write(tmpSpektrumDataAlt, 16); // send buffer
if (adr == 0x11) // check for speed request at adr 11
Wire.write(tmpSpektrumDataSpd, 16); // send buffer
}
This works with a Spectrum DX8 with telemetry module.
The Spectrum interface was made public on Sectrums home page. Technical documents.
There could be other devices on the I2C bus, the TWAMR should be set with as less bits as possible. So I think the better way to calculate the mask is:
AddrOr = Addr1 | Addr2 | Addr3 | Addr4 ...
AddrAnd = Addr1 & Addr2 & Addr3 & Addr4 ...
TWAMR = (AddrOr ^ AddrAnd) << 1
while TWAR can be set as either AddrOr or AddrAnd
In this way we can limit the possibility of address conflict to the minimum

I2C MCP3221 12 bit ADC reading 0 at any voltage

I've hooked up an MCP3221 to a Teensy 3.1 on the I2C bus and connect it to Vref(3.3V), just to check if it's working. However it's reading 0, even when I hook it up to a different voltage. Is my code faulty or should I just get a new device?
#include <MCP3221.h>
#include <Wire.h>
#include "SoftwareSerial.h"
#define ADDRESS 0x4D // 7 bits address is 0x4D, 8 bits is 0x9B
MCP3221 adc(155,0x3);
void setup() {
Serial.begin(9600);
Serial.println("First");
Wire.begin(); //connects I2C
}
void loop() {
Serial.println(adc.readI2CADC());
delay(10);
}
There is a list of device addresses in the Microchip data sheet DS21732C on the page 20.
Depends on the marking code on your chip.
You are not using the right address. You declare the constant but never use it. The adc declaration should be like this
MCP3221 adc(ADDRESS, 0x3);
Why? Doing a little search, I found out that instead of 8 bits address (155 in decimal or 0x9B in hexadecimal), you have to use 7 bits address, 0x4D in this case. You can see that in this example, too. I think you should have this example in the Arduino IDE, in File > Examples > MCP3221.
Looking at the example, seems like the second argument you passed to the adc can be wrong, too, but I'm not sure about this. Try a greater value if you see you always measure the same.

Reading a long text from GPRS Shield with Arduino

I am having hell with this and I know it is probably really simple. I am trying to read a text message from my Seeed GPRS shield. I have the shield setup as a software serial and I am displaying the information received from the GPRS to the serial monitor. I am currently sending all AT commands over serial while I work on my code. To display the data from the software serial to the serial monitor, I am using the following code.
while(GPRS.available()!=0) {
Serial.write(GPRS.read());
}
GPRS is my software serial obviously. The problem is, the text is long and I only get a few characters from it. Something like this.
+CMGR: "REC READ","1511","","13/12/09,14:34:54-24" Welcome to TM eos8
This text is a "Welcome to T-Mobile" text that is much longer. The last few characters shown are scrambled. I have done some research and have seen that I can mod the serial buffer size to 256 instead of the default 64. I want to avoid this because I am sure there is an easier way. Any ideas?
Have you tried reading into a character array, one byte at a time? See if this helps:
if (GPRS.available()) { // GPRS talking ..
while(GPRS.available()) { // As long as it is talking ..
buffer[count++]=GPRS.read();     
// read char into array
if(count == 64) break; // Enough said!
}
Serial.write(buffer,count); // Display in Terminal
clearBufferArray();
count = 0;
}
You need to declare the variables 'buffer' and 'count' appropriately and define the function 'clearBufferArray()'
Let me know if this helps.
Looks like this is simply the result of the lack of flow control in all Arduino serial connections. If you cannot pace your GPRS() input byte sequence to a rate that guarantees the input FIFO can't overflow, then your Serial.write() will block when the output FIFO fills. At that point you will be dropping new GPRS input bytes on the floor until Serial output frees up more space.
Since the captured output is apparently clean up to about 64 bytes, this suggests
a) a 64 byte buffer,
b) a GPRS data rate much higher than the Serial one, and
c) that the garbage data is actually the occasional valid byte from later in the sequence.
You might confirm this by testing the return code from Serial.write. If you get back zero, that byte is getting lost.
If you were using 9600 for Serial and 57600 for GPRS, I would expect somewhat more than 64 bytes to come through before the output gets mangled, but if the GPRS rate is more than 64x the Serial rate, the entire output FIFO could fill up within a single output byte transmission time.
Capturing to an intermediate buffer should resolve your issue, as long as it is large enough for the whole message. Similarly, extending the size of either the source (in conjunction with testing the Serial.write) or destination (without any additional code) FIFOs to the maximum datagram size should work.
I've had the same problem trying to read messages and get 64 characters. I overcame it by adding a "delay(10)" in the loop calling the function that does the read from the GPRS. Seems to be enough to overcome the race scenario. - Using Arduino Mega.
void loop() {
ReadmyGPRS();
delay(10); //A race condition exists to get the data.
}
void ReadmyGPRS(){
if (Serial1.available()){ // if data is comming from GPRS serial port
count = 0; // reset counter
while(Serial1.available()) // reading data into char array
{
buffer[count++]=Serial1.read(); // writing data into array
if(count == 160)break;
}
Serial.write(buffer,count);
}
}

Resources