Different behaviors with 2 arduino boards

Hello,
I have a strange phenomenon I am using a program with an Arduino Uno board this one works fine. I want to change the Arduino Uno board so I uploaded the program without any error, the program is initialized and when a command is launched via the serial port on the new board, nothing happens to the outputs. I tested blink on the new card and the program works.If I mount ATMega from the first card to the second it works, if I put ATMega from the second card on the first download ok the program starts but when I run a command via the serial port nothing is wrong happens at the level of the outputs. I also tried with other ATMega same issue, My program only works with only the first card which is very strange thank you for your help.

post your code.
Are you 100% sure the upload worked? how could you tell? (how do you know that "the program starts")

this is the execution of the beginning of the program who work
image
and after if i write for example d2 the program in the windows com5 ii updated but noaction at the output 5 see the second image.

when i use the first arduino card the action of the d2 is to shut down the store of my window.
see below the code from Romain Piquard has created this code.

#include <EEPROM.h>
#define PORT_TX 5
 
#define SYMBOL 640
#define HAUT 0x2
#define STOP 0x1
#define BAS 0x4
#define PROG 0x8
#define EEPROM_ADDRESS 0
 
#define VERSION 1
 
byte frame[7];
byte checksum;
 
struct Remote
{
  unsigned long remoteID;
  unsigned int rollingCode;
};
 
struct SomfyController
{
  int appVersion;
  Remote remotes[4];
};
 
SomfyController somfyControllers;
Remote newRemotes [4] = {
  {0x123456, 0},
  {0x123457, 0},
  {0x123458, 0},
  {0x123459, 0}
};
//456 cuisine cde 0,457 salon cde 1,458 chambre cyril cde 2,459 salle à manger cde 3
 
void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button);
void SendCommand(byte *frame, byte sync);
 
 
void setup()
{
  Serial.begin(115200);
  DDRD |= 1<<PORT_TX;
  PORTD &= !(1<<PORT_TX);
 
  EEPROM.get(EEPROM_ADDRESS, somfyControllers);
 
  if (somfyControllers.appVersion < VERSION)
  {
    Serial.println("La version de l'application en mémoire n'est pas dans la bonne version ou la mémoire est vide");
    somfyControllers.appVersion = VERSION;
    memcpy(&somfyControllers.remotes, &newRemotes, sizeof(newRemotes));
    
    EEPROM.put(EEPROM_ADDRESS, somfyControllers);
  }
 
  for (int i = 0; i < (sizeof(somfyControllers.remotes) / sizeof(Remote)); i++)
  {
    Remote currentRemote = somfyControllers.remotes[i];
    Serial.print("Commande ["); Serial.print(i); Serial.println("]");
    Serial.print("\tID de la commande : "); Serial.println(currentRemote.remoteID, HEX);
    Serial.print("\tCompteur actuel : "); Serial.println(currentRemote.rollingCode);
  }
}
 
void loop()
{
  if (Serial.available())
  {
    String data = "";
    
    while (Serial.available())
    {
      char c = Serial.read();
      Serial.print (c);
      data += String(c);
      Serial.print (data);
      delay(10);
    }
 
    char serie = data[0];
 
    for (int i = 1; i < data.length(); i++)
    {
      char cRemotePosition = data[i];
      
      int remotePosition = cRemotePosition - '0';
      Serial.print("Commande "); Serial.println(remotePosition);
 
      Remote remote = somfyControllers.remotes[remotePosition];
      unsigned long remoteID = remote.remoteID;
      unsigned int rollingCode = remote.rollingCode;
      
      Serial.println("");
      if (serie == 'm')
      {
        Serial.println("Monte");
        BuildFrame(remoteID, rollingCode, frame, HAUT);
      }
      else if (serie == 's')
      {
        Serial.println("Stop");
        BuildFrame(remoteID, rollingCode, frame, STOP);
      }
      else if (serie == 'd')
      {
        Serial.println("Descend");
        BuildFrame(remoteID, rollingCode, frame, BAS);
      }
      else if (serie == 'p')
      {
        Serial.println("Prog");
        BuildFrame(remoteID, rollingCode, frame, PROG);
      }
      else
      {
        Serial.println("Code custom");
        BuildFrame(remoteID, rollingCode, frame, serie);
      }
  
      Serial.println("");
      SendCommand(frame, 2);
      for (int i = 0; i < 2; i++)
      {
        SendCommand(frame, 7);
      }
  
      //Incrémente le compteur et le sauvegarde en mémoire
      somfyControllers.remotes[remotePosition].rollingCode++;
      EEPROM.put(EEPROM_ADDRESS, somfyControllers);
    }
  }
}
 
 
void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button)
{
  frame[0] = 0xA7;
  frame[1] = button << 4;
  frame[2] = rollingCode >> 8;
  frame[3] = rollingCode;
  frame[4] = remoteID >> 16;
  frame[5] = remoteID >>  8;
  frame[6] = remoteID;
 
  Serial.print("Frame         : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }
 
  checksum = 0;
  for (byte i = 0; i < 7; i++)
  {
    checksum = checksum ^ frame[i] ^ (frame[i] >> 4);
  }
  checksum &= 0b1111;
 
  frame[1] |= checksum;
 
 
  Serial.println(""); Serial.print("Avec checksum : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }
 
  for (byte i = 1; i < 7; i++)
  {
    frame[i] ^= frame[i-1];
  }
 
  Serial.println(""); Serial.print("Obfuscation    : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }
  Serial.println("");
  Serial.print("Compteur  : "); Serial.println(rollingCode);
}
 
void SendCommand(byte *frame, byte sync)
{
  if (sync == 2)
  {
    PORTD |= 1<<PORT_TX;
    delayMicroseconds(9415);
    PORTD &= !(1<<PORT_TX);
    delayMicroseconds(89565);
  }
 
  for (int i = 0; i < sync; i++)
  {
    PORTD |= 1<<PORT_TX;
    delayMicroseconds(4*SYMBOL);
    PORTD &= !(1<<PORT_TX);
    delayMicroseconds(4*SYMBOL);
  }
 
  PORTD |= 1<<PORT_TX;
  delayMicroseconds(4550);
  PORTD &= !(1<<PORT_TX);
  delayMicroseconds(SYMBOL);
  
  for (byte i = 0; i < 56; i++)
  {
    if (((frame[i/8] >> (7 - (i%8))) & 1) == 1)
    {
      PORTD &= !(1<<PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1<<PORT_TX;
      delayMicroseconds(SYMBOL);
    }
    else
    {
      PORTD |= (1<<PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1<<PORT_TX;
      delayMicroseconds(SYMBOL);
    }
  }
  
  PORTD &= !(1<<PORT_TX);
  delayMicroseconds(30415);
}

The way the Serial monitor commands are read is not great

In your image
image
you say you typed in d2, why do I see dd2d2 ? what about the -38 command ?

seems there is something wrong going with the parser

As you seem to speak french, I would suggest to replace the command management by taking ideas from my serial tutorial (in French)

there are also weird things going on like delayMicroseconds(89565); when the doc states the largest value that will produce an accurate delay is 16383 and 89565 does not fit on an unsigned int for an Arduino Uno board.. so the delays won't work...

yes i am french.
this is the capture of the commad when the strore close with the firs card who wotk.
image
if you prefer to move the topic no problem but they have a lot of support in english

English is fine - the French forum is pretty active too.

Did you recompile the code in the first arduino with a recent version of the IDE or is it something you have for a long time?

As I said there are weird things going on like delayMicroseconds(89565); when the doc states the largest value that will produce an accurate delay is 16383 and 89565 does not fit on an unsigned int for an Arduino Uno board.. so the delays won't work...

also when doing PORTD &= !(1 << PORT_TX); you should not use ! but ~

I did a bit of cleanup on the code to fix the delays, the ! into ~ and adjusted the Serial input to be more robust. Commands need to end with a new line '\n' character. '\r' is ignored. So if you send the commands from the IDE's serial monitor, make sure you set the baud rate to 115200 and the line ending to NL or N+CR

Of course I don't have that system so can't test nor say if what is done is what's supposed to happen in terms of signals

give it a try...

#include <EEPROM.h>
#define PORT_TX 5

#define SYMBOL 640u
#define HAUT 0x2
#define STOP 0x1
#define BAS 0x4
#define PROG 0x8
#define EEPROM_ADDRESS 0

#define VERSION 1u

byte frame[7];
byte checksum;

struct Remote
{
  uint32_t remoteID;
  uint16_t rollingCode;
};

Remote newRemotes[] = {
  {0x123456, 0}, // cuisine         cde 0
  {0x123457, 0}, // salon           cde 1
  {0x123458, 0}, // chambre cyril   cde 2
  {0x123459, 0}  // salle à manger  cde 3
};
const size_t nbRemotes = sizeof newRemotes / sizeof newRemotes[0];

struct SomfyController
{
  uint16_t appVersion;
  Remote remotes[nbRemotes];
} somfyControllers;


void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button);
void SendCommand(byte *frame, byte sync);

const byte tailleMessageMax = 50;
char message[tailleMessageMax + 1]; // +1 car on doit avoir un caractère de fin de chaîne en C, le '\0'

boolean ecouter()
{
  static byte indexMessage = 0; // static pour se souvenir de cette variable entre 2 appels consécutifs. initialisée qu'une seule fois.
  boolean messageEnCours = true;

  while (Serial.available() && messageEnCours) {
    int c = Serial.read();
    if (c != -1) {
      switch (c) {
        case '\r': break; // ignoré
        case '\n': // marqueur de fin
          message[indexMessage] = '\0'; // on termine la c-string
          indexMessage = 0; // on se remet au début pour la prochaine fois
          messageEnCours = false;
          break;
        default:
          if (indexMessage <= tailleMessageMax - 1) message[indexMessage++] = (char) c; // on stocke le caractère et on passe à la case suivante
          break;
      }
    }
  }
  return messageEnCours;
}

void setup()
{
  Serial.begin(115200); Serial.println(F("\n---- PREPARATION ---"));
  DDRD |= 1u << PORT_TX;
  PORTD &= ~(1u << PORT_TX);

  EEPROM.get(EEPROM_ADDRESS, somfyControllers);

  if (somfyControllers.appVersion != VERSION) {
    Serial.println("La version de l'application en mémoire n'est pas dans la bonne version ou la mémoire est vide");
    somfyControllers.appVersion = VERSION;
    memcpy(&somfyControllers.remotes, &newRemotes, sizeof(somfyControllers.remotes));
    EEPROM.put(EEPROM_ADDRESS, somfyControllers);
  }

  for (size_t i = 0; i < nbRemotes; i++) {
    Serial.print(F("Commande [")); Serial.print(i); Serial.print(F("] :"));
    Serial.print(F("ID #0x")); Serial.print(somfyControllers.remotes[i].remoteID, HEX);
    Serial.print(F("\tCompteur: ")); Serial.println(somfyControllers.remotes[i].rollingCode);
  }
  Serial.println(F("\n---- PRET ---"));
}

void loop() {
  if (! ecouter()) {
    size_t nbCar = strlen(message);
    if (nbCar > 1) {
      for (size_t i = 1; i < nbCar; i++) {
        byte remoteIndex = message[i] - '0';

        if (isdigit(message[i]) && (remoteIndex < nbRemotes)) {
          Serial.print(F("Commande [")); Serial.print(message[0]); Serial.print(F("]"));
          Serial.print(F(" sur télécommande #")); Serial.println(message[i]);

          // m = monte, s = stop, d = descend, p = prog, autre = code spécifique
          switch (message[0]) {
            case 'm':
              Serial.print(F("Monte #")); Serial.println(message[i]);
              BuildFrame(somfyControllers.remotes[remoteIndex].remoteID, somfyControllers.remotes[remoteIndex].rollingCode, frame, HAUT);
              break;

            case 's':
              Serial.print(F("Stop #")); Serial.println(message[i]);
              BuildFrame(somfyControllers.remotes[remoteIndex].remoteID, somfyControllers.remotes[remoteIndex].rollingCode, frame, STOP);
              break;

            case 'd':
              Serial.print(F("Descend #")); Serial.println(message[i]);
              BuildFrame(somfyControllers.remotes[remoteIndex].remoteID, somfyControllers.remotes[remoteIndex].rollingCode, frame, BAS);
              break;

            case 'p':
              Serial.print(F("Prog #")); Serial.println(message[i]);
              BuildFrame(somfyControllers.remotes[remoteIndex].remoteID, somfyControllers.remotes[remoteIndex].rollingCode, frame, PROG);
              break;

            default:
              Serial.print(F("Custom #")); Serial.println(message[i]);
              BuildFrame(somfyControllers.remotes[remoteIndex].remoteID, somfyControllers.remotes[remoteIndex].rollingCode, frame, message[0]);
              break;
          }
        }
        Serial.println();
        SendCommand(frame, 2);
        SendCommand(frame, 7);
        SendCommand(frame, 7);

        //Incrémente le compteur et le sauvegarde en mémoire
        somfyControllers.remotes[remoteIndex].rollingCode++;
        EEPROM.put(EEPROM_ADDRESS, somfyControllers);
      } // fin de pour chaque numéro de télécommande
    } // fin if commande assez longue
  }
}



void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button)
{
  frame[0] = 0xA7;
  frame[1] = button << 4;
  frame[2] = rollingCode >> 8;
  frame[3] = rollingCode;
  frame[4] = remoteID >> 16;
  frame[5] = remoteID >>  8;
  frame[6] = remoteID;

  Serial.print("Frame         : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }

  checksum = 0;
  for (byte i = 0; i < 7; i++)
  {
    checksum = checksum ^ frame[i] ^ (frame[i] >> 4);
  }
  checksum &= 0b1111;

  frame[1] |= checksum;


  Serial.println(""); Serial.print("Avec checksum : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }

  for (byte i = 1; i < 7; i++)
  {
    frame[i] ^= frame[i - 1];
  }

  Serial.println(""); Serial.print("Obfuscation   : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }
  Serial.println("");
  Serial.print("Compteur  : "); Serial.println(rollingCode);
}

void SendCommand(byte *frame, byte sync)
{
  if (sync == 2)
  {
    PORTD |= 1u << PORT_TX;
    delayMicroseconds(9415);
    PORTD &= (1u << PORT_TX);
    // delay for 89565 microseconds
    delay(89); delayMicroseconds(565);
  }

  for (int i = 0; i < sync; i++)
  {
    PORTD |= 1u << PORT_TX;
    delayMicroseconds(4 * SYMBOL);
    PORTD &= (1u << PORT_TX);
    delayMicroseconds(4 * SYMBOL);
  }

  PORTD |= 1u << PORT_TX;
  delayMicroseconds(4550);
  PORTD &= ~(1u << PORT_TX);
  delayMicroseconds(SYMBOL);

  for (byte i = 0; i < 56; i++)
  {
    if (((frame[i / 8] >> (7 - (i % 8))) & 1) == 1)
    {
      PORTD &= (1u << PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1u << PORT_TX;
      delayMicroseconds(SYMBOL);
    }
    else
    {
      PORTD |= (1u << PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1u << PORT_TX;
      delayMicroseconds(SYMBOL);
    }
  }

  PORTD &= ~(1u << PORT_TX);
  // delay for 30415 microseconds
  delay(30); delayMicroseconds(415);
}

if you type in d012 for example the Serial monitor will show

---- PREPARATION ---
Commande [0] :ID #0x123456	Compteur: 3
Commande [1] :ID #0x123457	Compteur: 3
Commande [2] :ID #0x123458	Compteur: 6
Commande [3] :ID #0x123459	Compteur: 3

---- PRET ---
Commande [d] sur télécommande #0
Descend #0
Frame         : A7 40 00 03 12 34 56 
Avec checksum : A7 4D 00 03 12 34 56 
Obfuscation   : A7 EA EA E9 FB CF 99 
Compteur  : 3

Commande [d] sur télécommande #1
Descend #1
Frame         : A7 40 00 03 12 34 57 
Avec checksum : A7 4C 00 03 12 34 57 
Obfuscation   : A7 EB EB E8 FA CE 99 
Compteur  : 3

Commande [d] sur télécommande #2
Descend #2
Frame         : A7 40 00 06 12 34 58 
Avec checksum : A7 46 00 06 12 34 58 
Obfuscation   : A7 E1 E1 E7 F5 C1 99 
Compteur  : 6

(with of course different values for Compteur as this will be related to what you have in EEPROM)

i use the ide 1.8.13 for the both card,i have tried your proposal ,and the program not work with the both Arduino and it is true the display is more clear shame.
my problem is why the program work in the first arduino but not in the second with the same ide version and the same configuration.is it the bootloader in the second arduino can be corrupt?

What does the working arduino display?
The remote IDs seems weird

Hi,
what do you mean the working arduino display if it the screen with the Arduino who work you Can see in previous answer.

OK so the IDs are really 0x123456, 0x123457, 0x123458 and 0x123459 ?

and the code in the Arduino that works, is it the same code that you upload or an old version you uploaded a long time ago and was not overwritten?

when you say it works, do you see any activity on your somfy motors (I suspect this is what you drive)?

Yes the code is the same version.They are uploaded at the same time
Yes when it work the Somfy motor run

Ok

May be you should force a clean slate for the eeprom of the non working arduino. Just add in the setup to force a memory reset


somfyControllers.appVersion = VERSION;
memcpy(&somfyControllers.remotes, &newRemotes, sizeof(newRemotes));
EEPROM.put(EEPROM_ADDRESS, somfyControllers);

Run it once, remove it and then run again

With all the bitwise errors and delayMicroseconds challenges I’m not sure why this works in real life, may be just the author got lucky with rounding…

I tried and the same result, it is hopeless, I can't understand that it works with one and not with the other.
do you know how can totaly reset the chip ATMega i could try it and after i could put the bootloader and load the program

You could try to reinstall the bootloader… but what you describe is very weird… say Arduino A is working, if you extract the chip from A and install it on arduino B then B works but the chip of B installed in A does not?

Do you have two different systems or do you wire everything up again?

Post a full schema of what you have

i wire everything up again on each card ,the connections are very simple only 3 pins.

OK - and so when you just switch the ATMEGA chip one works and the other does not?

Yes and i have tried whith several chips juste one works

And you are sure it’s the exact same 328p?

Atmega328p-pu on the card who work
Atmega328p-u on the second Arduino card.i have round an explanation about the différence
See below
Mouser finally emailed back. They contacted Microchip for me who said this:

As part of Part marking change due to the migration from Atmel to Microchip, the package identifier has been removed from the device marking as this can be observed visually for different packages. This will be updated in the upcoming revisions of the device datasheet. As per this new marking the ATMEGA328P U are valid devices without any process change.