Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@tuenhidiy
Created January 28, 2018 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tuenhidiy/fb2bec2b09bbd5104f5c2f2cfaace35e to your computer and use it in GitHub Desktop.
Save tuenhidiy/fb2bec2b09bbd5104f5c2f2cfaace35e to your computer and use it in GitHub Desktop.
NodeMCU control PLC through Wifi network
/*----------------------------------------------------------------------
Thank to Davide Nardella
----------------------------------------------------------------------*/
// Wifi -> #define S7WIFI
// Cable -> #define S7WIRED
#define S7WIFI
#include <SPI.h>
#include <Ethernet.h>
#ifdef S7WIFI
#include <ESP8266WiFi.h>
#endif
#include "Settimino.h"
#include <Wire.h>
// MPU6050 Slave Device Address
const uint8_t MPU6050SlaveAddress = 0x68;
// Select SDA and SCL pins for I2C communication
const uint8_t scl = D1;
const uint8_t sda = D2;
// sensitivity scale factor respective to full scale setting provided in datasheet
const uint16_t AccelScaleFactor = 16384;
const uint16_t GyroScaleFactor = 131;
// MPU6050 few configuration register addresses
const uint8_t MPU6050_REGISTER_SMPLRT_DIV = 0x19;
const uint8_t MPU6050_REGISTER_USER_CTRL = 0x6A;
const uint8_t MPU6050_REGISTER_PWR_MGMT_1 = 0x6B;
const uint8_t MPU6050_REGISTER_PWR_MGMT_2 = 0x6C;
const uint8_t MPU6050_REGISTER_CONFIG = 0x1A;
const uint8_t MPU6050_REGISTER_GYRO_CONFIG = 0x1B;
const uint8_t MPU6050_REGISTER_ACCEL_CONFIG = 0x1C;
const uint8_t MPU6050_REGISTER_FIFO_EN = 0x23;
const uint8_t MPU6050_REGISTER_INT_ENABLE = 0x38;
const uint8_t MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B;
const uint8_t MPU6050_REGISTER_SIGNAL_PATH_RESET = 0x68;
int16_t AccelX, AccelY, AccelZ, Temperature, GyroX, GyroY, GyroZ;
#define DO_IT_SMALL
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0x90, 0xA2, 0xDA, 0x0F, 0x08, 0xE11 };
IPAddress Local(192,168,0,70); // Local Address
IPAddress PLC(192,168,0,71); // PLC Address
// Following constants are needed if you are connecting via WIFI
// The ssid is the name of my WIFI network (the password obviously is wrong)
char ssid[] = "FPT-Telecom"; // Your network SSID (name)
char pass[] = "12345689"; // Your network password (if any)
IPAddress Gateway(192, 168, 0, 1);
IPAddress Subnet(255, 255, 255, 0);
int DBNum = 2; // This DB must be present in your PLC
byte Buffer[512];
#ifdef S7WIFI
// S7Client will create a WiFiClient as TCP Client
S7Client Client(_S7WIFI);
#else
// S7Client will create an EthernetClient as TCP Client
S7Client Client(_S7WIRED);
#endif
unsigned long Elapsed; // To calc the execution time
//----------------------------------------------------------------------
// Setup : Init Ethernet and Serial port
//----------------------------------------------------------------------
void setup() {
// Open serial communications and wait for port to open:
Wire.begin(sda, scl);
MPU6050_Init();
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
#ifdef S7WIFI
//--------------------------------------------- ESP8266 Initialization
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
WiFi.config(Local, Gateway, Subnet);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Local IP address : ");
Serial.println(WiFi.localIP());
#else
//--------------------------------Wired Ethernet Shield Initialization
// Start the Ethernet Library
Ethernet.begin(mac, Local);
// Setup Time, someone said me to leave 2000 because some
// rubbish compatible boards are a bit deaf.
delay(2000);
Serial.println("");
Serial.println("Cable connected");
Serial.print("Local IP address : ");
Serial.println(Ethernet.localIP());
#endif
}
//----------------------------------------------------------------------
// Connects to the PLC
//----------------------------------------------------------------------
bool Connect()
{
int Result=Client.ConnectTo(PLC,
0, // Rack (see the doc.)
2); // Slot (see the doc.)
Serial.print("Connecting to ");Serial.println(PLC);
if (Result==0)
{
Serial.print("Connected ! PDU Length = ");Serial.println(Client.GetPDULength());
}
else
Serial.println("Connection error");
return Result==0;
}
//----------------------------------------------------------------------
// Dumps a buffer (a very rough routine)
//----------------------------------------------------------------------
void Dump(void *Buffer, int Length)
{
int i, cnt=0;
pbyte buf;
if (Buffer!=NULL)
buf = pbyte(Buffer);
else
buf = pbyte(&PDU.DATA[0]);
Serial.print("[ Dumping ");Serial.print(Length);
Serial.println(" bytes ]==========================");
for (i=0; i<Length; i++)
{
cnt++;
if (buf[i]<0x10)
Serial.print("0");
Serial.print(buf[i], HEX);
Serial.print(" ");
if (cnt==16)
{
cnt=0;
Serial.println();
}
}
Serial.println("===============================================");
}
//----------------------------------------------------------------------
// Prints the Error number
//----------------------------------------------------------------------
void CheckError(int ErrNo)
{
Serial.print("Error No. 0x");
Serial.println(ErrNo, HEX);
// Checks if it's a Severe Error => we need to disconnect
if (ErrNo & 0x00FF)
{
Serial.println("SEVERE ERROR, disconnecting.");
Client.Disconnect();
}
}
//----------------------------------------------------------------------
// Profiling routines
//----------------------------------------------------------------------
void MarkTime()
{
Elapsed=millis();
}
//----------------------------------------------------------------------
void ShowTime()
{
// Calcs the time
Elapsed=millis()-Elapsed;
Serial.print("Job time (ms) : ");
Serial.println(Elapsed);
}
//----------------------------------------------------------------------
// Main Loop
//----------------------------------------------------------------------
void loop()
{
int Size, Result;
void *Target;
double Ax, Ay, Az, T, Gx, Gy, Gz;
double roll = 0.00, pitch = 0.00; //Roll & Pitch are the angles which rotate by the axis X and y
Read_RawValue(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H);
//divide each with their sensitivity scale factor
Ax = (double)AccelX/AccelScaleFactor;
Ay = (double)AccelY/AccelScaleFactor;
Az = (double)AccelZ/AccelScaleFactor;
T = (double)Temperature/340+36.53; //temperature formula
Gx = (double)GyroX/GyroScaleFactor;
Gy = (double)GyroY/GyroScaleFactor;
Gz = (double)GyroZ/GyroScaleFactor;
roll = atan2(Ay , Az) * 57.3;
pitch = atan2((- Ax) , sqrt(Ay * Ay + Az * Az)) * 57.3;
//Serial.print(" Roll: "); Serial.println(roll);
//Serial.print(" Pitch: "); Serial.println(pitch);
//Serial.print(" Az: "); Serial.print(Az);
//Serial.print(" T: "); Serial.print(T);
//Serial.print(" Gx: "); Serial.print(Gx);
//Serial.print(" Gy: "); Serial.print(Gy);
//Serial.print(" Gz: "); Serial.println(Gz);
delay(100);
//----------------------------------------------------------------------
// Programm_for as to variable Int
//----------------------------------------------------------------------
int write_data = (int)(map(roll, -180, 180, -1000, 1000)); //// Write roll to PLC
//Serial.print(" Write data prepare: ");Serial.println(write_data);
//delay(500);
//----------------------------------------------------------------------
// Start connessione DB
//----------------------------------------------------------------------
#ifdef DO_IT_SMALL
Size=2;
Target = NULL; // Uses the internal Buffer (PDU.DATA[])
#else
Size=1024;
Target = &Buffer; // Uses a larger buffer
#endif
// Connection
while (!Client.Connected)
{
if (!Connect())
delay(500);
}
//----------------------------------------------------------------------
// Little_Endian & Big_Endian convertion
//----------------------------------------------------------------------
int write_data_var1 = write_data;
byte* bytes = (byte*)& write_data_var1;
//----------------------------------------------------------------------
// Word/Int Correction
//----------------------------------------------------------------------
void Correction(void *bytes);
{
byte *pointerbyte;
byte temp;
pointerbyte=(byte*)(bytes);
// Swap byte
temp=*(pointerbyte+1);
*(pointerbyte+1) = *pointerbyte;
*pointerbyte = temp;
}
//----------------------------------------------------------------------
// Serial check
//----------------------------------------------------------------------
Serial.print("Write ");Serial.print(Size);Serial.println(" bytes from DB1.DBB0");
// Put the current tick
MarkTime();
Result=Client.WriteArea(S7AreaDB, // We are requesting DB access
1, // DB Number = 1
0, // Start from byte N.0
Size, // We need "Size" bytes
bytes); // Put them into our target (Buffer or PDU)
if (Result==0)
{
ShowTime();
Dump(Target, Size);
}
else
CheckError(Result);
delay(500);
}
void I2C_Write(uint8_t deviceAddress, uint8_t regAddress, uint8_t data){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.write(data);
Wire.endTransmission();
}
// read all 14 register
void Read_RawValue(uint8_t deviceAddress, uint8_t regAddress){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.endTransmission();
Wire.requestFrom(deviceAddress, (uint8_t)14);
AccelX = (((int16_t)Wire.read()<<8) | Wire.read());
AccelY = (((int16_t)Wire.read()<<8) | Wire.read());
AccelZ = (((int16_t)Wire.read()<<8) | Wire.read());
Temperature = (((int16_t)Wire.read()<<8) | Wire.read());
GyroX = (((int16_t)Wire.read()<<8) | Wire.read());
GyroY = (((int16_t)Wire.read()<<8) | Wire.read());
GyroZ = (((int16_t)Wire.read()<<8) | Wire.read());
}
//configure MPU6050
void MPU6050_Init(){
delay(150);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV, 0x07);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG, 0x00);//set +/-250 degree/second full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG, 0x00);// set +/- 2g full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL, 0x00);
}
@methaqali
Copy link

nice, can you make code for LSIS plc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment