element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
On the Line
  • Challenges & Projects
  • Design Challenges
  • On the Line
  • More
  • Cancel
On the Line
Forum On The line Challenge: development
  • News
  • Projects
  • Forum
  • DC
  • Leaderboard
  • Files
  • Members
  • More
  • Cancel
  • New
Join On the Line to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 0 replies
  • Subscribers 33 subscribers
  • Views 19 views
  • Users 0 members are here
  • industrial
  • On The Line
  • programming
  • arduino
Related

On The line Challenge: development

SensoredHacker0
SensoredHacker0 15 days ago

Well, there are officially 2 people using my Maintenance Protocol implementation in control applications.
it enables treating PLCs like netowork peripherals. This means you can have the PLC, and get all the IO functionality, and program in whatever language you want. 

This is the design implementation Im shooting for with having an arduino act as a PLC. 
full operability with the PLC, HMI, client devices, or PC, offering all the busses and IO from the auduino. 

hows it going?
Well, it was going great. Im learning more about the HMI. 
The downside of attaching the HMi to an arduino acting as a PLC is that 1, I have not implemented and API yet, and 2, 
That one has to define anything to begin with. The UNO Q isnt working out for me, but I really want that extra memory. 

where I do not have the extra memory, I have this issue of not having the registers ready to go. 
If I add 100 points to monitor, the arduino needs those registers ready to go when the HMI ask, or within 0.5 seconds, 
which is the hmi update timeout. fortunately, those registers only need to be available, they dont need real data in them. 

Im not sure if there is a method that would use minimal memory to respond with.... IDK theres a bunch of things to consider. 
this is the same on the PLC, but where Im implementing the arduino as a server, now I have to think about it. 
well, I dont mind having a sparse list. 

The HMI initialization always requies additional registers upon inclusion.
The fc6a client library has no such requirements, it just reads values as they return, and or writes them, but it doesn't expect anything. 
The HMI isnt like that. if registers are defined, but not responding, the HMI is not going to initialize properly. 
 
Whats the point of this? One of the users here said something like you're going to have someone write PLC code with NV4 / windLDR, and arduino code, and some other PC code. ..?
well, I understand that confusion. This is actually not the case.  the PLC doesn't require code to be treated as a peripheral. in fact, it might work better without code on it. 
Thats been a pretty unpopular idea, and I dont want to get into it right now.

The arduino here is just going to respond as a PLC would, with resulting IO from IO / buses as PLC registers. 

So, Im going to write the IO and bus  functions, with a listener / debugger. Thats minimal ram. 
just defining the operations as PLC constructs is its own trouble.  the idea now is to create a register buffer to whatever size I can manage, and populate it with arduino IO handlers. 



#include <SPI.h>
#include <Ethernet.h>

// Network config
byte mac[] = { 0x00, 0x03, 0x7B, 0x20, 0xFE, 0xED };
byte ip[]  = { 192, 168, 1, 50 };

EthernetServer server(2101);

// Test register values
uint16_t readDWord(int addr) {
  switch (addr) {
    case 158: return random(50, 101);   // HMI test value
    case 560: return 26;    // HMI expected value
    case 562: return 0;
    case 564: return 0;
    case 566: return 0;
    case 568: return 0;
    case 570: return 0;
    case 572: return 0;
      return 0;

    default:
      return 0;
  }
}

// BCC helpers
byte xorBcc(byte *data, int len) {
  byte bcc = 0;
  for (int i = 0; i < len; i++) {
    bcc ^= data[i];
  }
  return bcc;
}

void printHex(const char *label, const byte *buf, int len) {
  Serial.print(label);
  Serial.print(": ");
  for (int i = 0; i < len; i++) {
    if (buf[i] < 16) Serial.print("0");
    Serial.print(buf[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

// Reply builder
void replyReadD(EthernetClient &c, int addr, int nbytes) {
  byte tx[96];
  int p = 0;

  tx[p++] = 0x06;   // ACK
  tx[p++] = '0';    // reply device 00
  tx[p++] = '0';
  tx[p++] = '0';    // OK discontinued

  int words = nbytes / 2;

  for (int i = 0; i < words; i++) {
    uint16_t v = readDWord(addr + i);

    const char *h = "0123456789ABCDEF";
    tx[p++] = h[(v >> 12) & 0xF];
    tx[p++] = h[(v >> 8)  & 0xF];
    tx[p++] = h[(v >> 4)  & 0xF];
    tx[p++] = h[v & 0xF];
  }

  byte bcc = xorBcc(tx, p);

  const char *h = "0123456789ABCDEF";
  tx[p++] = h[(bcc >> 4) & 0xF];
  tx[p++] = h[bcc & 0xF];
  tx[p++] = '\r';

  printHex("TX", tx, p);
  c.write(tx, p);
}

// Main handler
void handle(EthernetClient c) {
  byte buf[64];
  int len = 0;

  unsigned long lastRx = millis();

  while (c.connected() && (millis() - lastRx < 3000)) {
    while (c.available()) {
      lastRx = millis();

      byte b = c.read();

      if (len < 64) {
        buf[len++] = b;
      }

      if (b == 0x0D) {
        printHex("RX", buf, len);

        if (len >= 14 && buf[0] == 0x05 && buf[4] == 'R' && buf[5] == 'D') {
          char a[5] = {
            (char)buf[6], (char)buf[7],
            (char)buf[8], (char)buf[9], 0
          };

          char l[3] = {
            (char)buf[10], (char)buf[11], 0
          };

          int addr = atoi(a);
          int nbytes = strtol(l, NULL, 16);

          Serial.print("READ D");
          Serial.print(addr);
          Serial.print(" nbytes=");
          Serial.println(nbytes);

          replyReadD(c, addr, nbytes);
        }

        len = 0;
      }
    }
  }

  c.stop();
}

void setup() {
  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  delay(1000);

  server.begin();
  randomSeed(analogRead(0));

  Serial.print("Listening on ");
  Serial.print(Ethernet.localIP());
  Serial.println(":2101");
}

void loop() {
  EthernetClient client = server.available();

  if (client) {
    Serial.println("Client connected");
    handle(client);
    Serial.println("Client done");
  }
}

 
 LoL: what with the code block?

  • Sign in to reply
  • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube