atemga 2560 vs 328p timing issues?

Hello,

I am currently working on a 2-wire bus system based on the atmega 328p microcontroller. The system consist of a master board connected to the slave boards via the same pwn i/o pin(and ground). So far I have used the arduino uno for prototyping, and the system is working fine.

The master will serve other functions besides bus control, and I realize it will be necessary with more i/o pins. (for the master) . I recently bought an arduino mega 2560, to use as the new master prototype board. As the bus relies on timing loops, pulsIN and Delay functions , I wanted the new MCU running at the same clock frequency(16Mhz) and with the same internal architecture.

As far as I can see, the the 328P and 2560 are similar processors, expect for the i/o. On the arduino boards, they are both running at 16Mhz.

I have tried porting the code directly by selecting Mega 2560 in IDE, I am currently using pwm pin nr. 5 on both master (2560) and slave (328P) boards. Unfortunately the code is not working with the mega board!

Any suggestions on where to start looking? I guess I am looking at an timing issue….
Does the 2560 execute instructions faster the 328P?

Thanks.

Jonas

jonastr:
Does the 2560 execute instructions faster the 328P?

Any differences will be irrelevant for the vast majority of situations.

Unfortunately the code is not working with the mega board!

Which code is that?

They are the same speed. The ATmega2560 has more memory, and it might use large pointers for that, that might make it a little slower.

Show us your sketch.

The Arduino uses Timer0 for millis(). That interrupt could delay the code.

Do you want to invent your own communication in software with pins ? why ?

Interrupts and function calls (and their matching return statements) will be a tad slower on the 2560 as it has to push /pop three address bytes instead of two on/from the stack; two times one instruction cycle difference.

Thanks for promt reply folks! I decided to implement this bus several reasons

  • SPI uses too many wires
  • I2C is used for the loacal bus on each node.
  • Want to be able to decide package size and protocol
  • Can be ported to other systems, as it use standard i/o pins.

The entire sketch is quite long, but I will include the functions for receiving (first one) and sending on the data line. Apologies for comments in Norwegian and the odd variable names.

int motta_data()                                                    //Funksjonen venter venter på startpuls og mottar deretter ALLE datapulser i pakken. Returnerer deretter mottatt data.
{
int mottatt_data=0;
pinMode(data_pin,INPUT);

do                                                                  //Venter på startpuls som ligger mellom 2500 og 2700 uS
{
  result = pulseIn(data_pin,LOW);
  //Serial.print(result);
  //Serial.print("\n");
  if(result == 0)                                                   //Dersom pulsIn ikke mottar en startpuls innen timeout på 1sek, avsluttes løkken og programmet hopper til "ny foresporsel"
  {                                                                 //Programmet går deretter tilbake til hovedløkken, der en ny foresporsel til node blir sendt.
   goto ny_foresporsel;                 
  }
  
} while (result < 2500 || result > 2700  );  
mdata[0] = result;


counter = 1;                                         
do
{
 mdata[counter]  = pulseIn(data_pin,LOW);
 result = mdata[counter];
 counter++;
 
 if(result == 0)                                                    //Dersom pulsIn ikke mottar en stoppuls innen timeout på 1sek, avsluttes løkken og programmet hopper til "ny foresporsel"
  {                                                                  //Programmet går deretter tilbake til hovedløkken, der det på nytt prøver å sende en foresporsel til node.
   goto ny_foresporsel;                 
  }
 
} while ((result < 1900) || (result > 2100));                       //Venter på stoppuls som ligger mellom 1900 og 2100 uS  


digitalWrite(12,HIGH);

counter=9;
                                                                    //Leser inn mottatt pulsbereddedata fra inngangsregister og oversetter dette til data bit.    
while(counter < antall_databit-1)                                   //Data bir blir lagert i registeret "mottatt_data"
{
 
  
 if(mdata[counter] < 1400 && mdata[counter] > 1200 )
 {
 bitSet(mottatt_data,counter-9);
 }
 
 else if(mdata[counter] < 700 && mdata[counter] > 500 )
 {
 bitClear(mottatt_data,counter-9);
 }
 
 else
 {
   Serial.print("Invalid pulse lenght");
   Serial.print("\n");
   Serial.print("");
 }
 
  counter++;   
}

ny_foresporsel:
delayMicroseconds(1);               //Må være her.
counter = 0;

return mottatt_data;

}





int send_data(int databyte_inn,int adresse_inn, int kommando_inn)     //Funksjone sender 1stk datapuls, returnerer deretter hovedloop. Når samtlige pulser er sendt, returneres "1" 
{
pinMode(data_pin, OUTPUT);                                           //setter til utgang, og gjør dermed beslag på datalinjen 
digitalWrite(data_pin, HIGH);                                        //setter utgang til høy

int data_sendt =0;                                                   //lokal variabel. Settes til "1" og innhold retrunres, når data er ferdig sendt.

if(counter == 0)                                                     //Venter i 5ms før første datapuls sendes. Dette gir mottaker tid å forberede mottak av data
{
  delay(5); 
}

if(counter == 0)                                                     //legger til startpuls,stoppuls,kommando og addresse i register. Dette skje kun første gang etter en ny pakke skal sendes.
{

  counter = 1;                                              
  while(counter < 5)                                                //LEGGER TIL ADRESSE
  {
   if(bitRead(adresse_inn,counter-1) == 1)
  {
   mdata[counter] = 200;
  }
 
  else if(bitRead(adresse_inn,counter-1) == 0)
  {
   mdata[counter] = 100;
  }
  counter ++;
 }  


while(counter < 9)                                                 //LEGGER TIL KOMMANDO
  {
  if(bitRead(kommando_inn,counter-5) == 1)
  {
    mdata[counter] = 200;
  }
 
else if(bitRead(kommando_inn,counter-5) == 0)
  {
  mdata[counter] = 100;
  }
  counter ++;
 }  
    
    
counter = 9;
mdata[antall_databit-1] = 300;                                       // stoppuls   
mdata[0] = 400;                                                      //  startpuls
while(counter < antall_databit-1)                                    // teller 8bit + 1paritetsbit
{

//Serial.print(counter);
//Serial.print("\n");
//Serial.print("");



if(bitRead(databyte_inn,counter-9) == 1)                             //LEGGER INN DATA SOM SKAL OVERFØRES I REGISTER
 {
 mdata[counter] = 200;
 }
 
else if(bitRead(databyte_inn,counter-9) == 0)
 {
 mdata[counter] = 100;
 }
 
else
 {
   Serial.print("Invalid");
   Serial.print("\n");
   Serial.print("");
 }
counter++;
} 
counter = 0;
}
 
for(unsigned long pwm=0;pwm < mdata[counter];pwm++)                 //agir tiden for lav puls (kommunikasjonsdelen)
{ 
digitalWrite(data_pin,LOW);
} 
for(unsigned long pwm=0;pwm < 50;pwm++)                            //angir minimustiden for høy puls(hviledelen)
{ 
digitalWrite(data_pin,HIGH);

} 
//Serial.print(mdata[counter]);
//Serial.print("\n");
counter++;

if(counter == antall_databit)
{
  counter = 0;
  data_sendt = 1;                                                    // Setter lokalvariable til 1
  pinMode(data_pin,INPUT);                                           //Frigjør/"slipper" databussen ved å sette pin til inngang
 
} 
return data_sendt;                                                   // Returnerer lokalvariabel                
}

Moderator edit : CODE TAGS.

Please read number 7 about code tags : http://forum.arduino.cc/index.php/topic,148850.0.html

That is not two complete sketches.

Not only the timer0 interrupt will happen, but also interrupts for the Serial.
You use a delay by doing digitalWrite() many times ? That is strange.
The communication uses the width of the pulse to send data ?

jonastr, I doubt if you can make it reliable.
The chips have hardware for: UART (Serial), SPI and I2C.
If you don't want to use those, then you create something like the SoftwareSerial library.
The SoftwareSerial uses software only, but it won't work when there are many others things going on.
The SoftwareSerial is complex, it is very hard to write something similar like that.

To create your own reliable communication, I think that handshake signals are required.

If you write documentation how your protocol works, I can have a look at it.

Use an Arduino Due (lots of pins) or a Teensy 3 (more pins than an Uno but fiddly to solder to them all). They both have two I2C ports. You can make all the subsidiary ones slaves of the master and they can each be master on their own local I2C bus.

The Teensy also has three hardware serial plus USB serial, so maybe you could use serial for the slaves?