unsigned int crc_16 (unsigned char *buffer, unsigned int length)
{
unsigned int i, j, temp_bit, temp_int, crc;
crc = 0xFFFF;
for ( i = 0; i < length; i++ )
{
temp_int = (unsigned char) *buffer++;
crc ^= temp_int;
for ( j = 0; j < 8; j++ )
{
temp_bit = crc & 0x0001;
crc >>= 1;
if ( temp_bit != 0 )
crc ^= 0xA001;
}
}
}
static unsigned int crc_16(unsigned char *buffer, unsigned int length)
{
unsigned int i, j, temp_bit, temp_int, crc;
crc = 0xFFFF;
for (i = 0; i < length; i++)
{
temp_int = (unsigned char) *buffer++;
crc ^= temp_int;
for (j = 0; j < 8; j++)
{
temp_bit = crc & 0x0001;
crc >>= 1;
if (temp_bit != 0)
crc ^= 0xA001;
}
}
return crc;
}
static unsigned char cmd[10];
static unsigned long timer = 0;
void setup()
{
Serial.begin(9600, SERIAL_8N1);
}
void loop()
{
if ((millis() - timer) > 1000lu)
{
timer = millis();
unsigned int count = 0;
cmd[count++] = 0x01; /* device address */
cmd[count++] = 0x03; /* function code (read holding registers) */
cmd[count++] = 0x00; /* register start (high) */
cmd[count++] = 0x00; /* register start (low) */
cmd[count++] = 0x00; /* register count (high) */
cmd[count++] = 0x10; /* register count (low) */
unsigned int crc = crc_16(cmd, count);
cmd[count++] = (crc >> 8) & 0xff;
cmd[count++] = crc & 0xff;
Serial.write(cmd, count);
}
}
@taydin hocam, daha önce modbus kullandınızmı bilmiyorum. Sanki mesajlarınızdan daha önce tecrübe etmemiş olduğunüz izlemine kapılıyorum. Önerim ilk önce bilgisayar ile sürücü haberleştirin. Modbuspoll programı işinizi fazlasıyla görecektir.Sadece veri yollanacak. Ama doğru yollandığını kontrol etmek için parametreleri geri okumak istiyorum.
@taydin hocam, daha önce modbus kullandınızmı bilmiyorum. Sanki mesajlarınızdan daha önce tecrübe etmemiş olduğunüz izlemine kapılıyorum. Önerim ilk önce bilgisayar ile sürücü haberleştirin. Modbuspoll programı işinizi fazlasıyla görecektir.
Asıl kontrol noktasını unuttum. Buna geçmişte bende düştüm ve canım çok yanmıştı
Arduino gönderme modundan önde max485 entegresini transmit moda almak gerekiyor, gönderme bittikten sonrada tekrar receive moduna almak gerekiyor.
#define PIN_DE 8
#define PIN_RE 9
static unsigned char cmd[10];
static unsigned long timer = 0;
static unsigned int crc_16 (unsigned char *buffer, unsigned int length)
{
unsigned int i, j, temp_bit, temp_int, crc;
crc = 0xFFFF;
for ( i = 0; i < length; i++ )
{
temp_int = (unsigned char) *buffer++;
crc ^= temp_int;
for ( j = 0; j < 8; j++ )
{
temp_bit = crc & 0x0001;
crc >>= 1;
if ( temp_bit != 0 )
crc ^= 0xA001;
}
}
return crc;
}
static void tx_mode()
{
digitalWrite(PIN_DE, 1);
digitalWrite(PIN_RE, 1);
}
static void rx_mode()
{
digitalWrite(PIN_DE, 0);
digitalWrite(PIN_RE, 0);
}
void setup()
{
Serial.begin(9600, SERIAL_8N1);
pinMode(PIN_DE, OUTPUT);
pinMode(PIN_RE, OUTPUT);
}
void loop()
{
if ((millis() - timer) > 1000lu)
{
timer = millis();
unsigned int reg_addr = 40301; // converter version
unsigned int count = 0;
cmd[count++] = 0x01; // device address
cmd[count++] = 0x03; // function code (read holding registers)
cmd[count++] = (reg_addr >> 8) & 0xff; // register start (high)
cmd[count++] = reg_addr & 0xff; // register start (low)
cmd[count++] = 0x00; // register count (high)
cmd[count++] = 0x01; // register count (low)
unsigned int crc = crc_16(cmd, count);
cmd[count++] = (crc >> 8) & 0xff;
cmd[count++] = crc & 0xff;
tx_mode();
delay(1);
Serial.write(cmd, count);
Serial.flush();
delay(1);
rx_mode();
}
}
tx_mode();
delay(1); // buradaki gecikmeyi >4ms şeklinde denermisiniz.
Serial.write(cmd, count);
Serial.flush();
delay(1);
rx_mode();
Gönderme öncesi beklemeyi 1ms yerine 4ms veya daha büyük denermisiniz.
Not: Yukarıda resimdede işaretleyerek göstermiştim. 3.5 karakteri 9600 baud da iletmek için gereken süreden fazla olmak zorunda.
C:tx_mode(); delay(1); // buradaki gecikmeyi >4ms şeklinde denermisiniz. Serial.write(cmd, count); Serial.flush(); delay(1); rx_mode();