I think I missed something in my code.
Below is my code in C#
public Form1()
{
InitializeComponent();
serialPort1.PortName = "COM2";
serialPort1.BaudRate = 9600;
serialPort1.Parity = Parity.None;
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Handshake = Handshake.RequestToSend;
serialPort1.DtrEnable = true;
serialPort1.RtsEnable = true;
serialPort1.NewLine = System.Environment.NewLine;
}
private void btnSend_Click(object sender, EventArgs e)
{
serialPort1.Open();
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
string num = "+639952006630\n";
serialPort1.Write(num);
string message = "Your child arrived at our school at " + DateTime.Now + ".";
serialPort1.Write(message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Below is my code in Arduino for sending data using GSM module SIM800L
#include <SoftwareSerial.h>
//SIM800 TX is connected to Arduino D8
#define SIM800_TX_PIN 8
//SIM800 RX is connected to Arduino D7
#define SIM800_RX_PIN 7
//Create software serial object to communicate with SIM800
SoftwareSerial serialSIM800(SIM800_TX_PIN,SIM800_RX_PIN);
void setup() {
//Begin serial comunication with Arduino and Arduino IDE (Serial Monitor)
Serial.begin(9600);
while(!Serial);
//Being serial communication with Arduino and SIM800
serialSIM800.begin(9600);
delay(1000);
//Set SMS format to ASCII
serialSIM800.write("AT+CMGF=1\r\n");
delay(1000);
//getting the number
char remoteNum[20]; // telephone number to send sms
readSerial(remoteNum);
//Send new SMS command and message number
serialSIM800.print("AT+CMGS=\"");
serialSIM800.print(remoteNum);
serialSIM800.print("\"\r\n");
delay(1000);
// getting sms text
char txtMsg[200];
readSerial(txtMsg);
//Send SMS content
serialSIM800.print(txtMsg);
delay(1000);
//Send Ctrl+Z / ESC to denote SMS message is complete
serialSIM800.write((char)26);
delay(1000);
Serial.println("SMS Sent!");
}
/*
Read input serial
*/
char readSerial(char result[]) {
int i = 0;
while (1) {
while (Serial.available() > 0) {
char inChar = Serial.read();
if (inChar == '\n') {
result[i] = '\0';
Serial.flush();
return 0;
}
if (inChar != '\r') {
result[i] = inChar;
i++;
}
}
}
}
void loop() {
}
My confusion/question here is
Whenever I test it using Serial Monitor in Arduino, the code in Arduino sends message to the cellular number successful. But when I use a form in Visual Studio using C#, nothing happens. There are also no errors that appear. I tried F11 also to know if I am missing an error, still I see nothing. But the application does not send SMS to the number.
Help from you guys is very much appreciated. Thank you in advance.
The solution is as obvious as simple. You have all your routines in the Arduino setup which runs only once. So sending one sms from Arduino directly works exactly 1 time.
When connecting via c code, the Arduino is already booted and in the EMPTY loop. So the chance to hit the one time run code is zero.
Put your routines especially
readSerial(remoteNum);
in the loop and it should work as expected.
The first thing you should do before sending the commands with your Visual Studio is that the serialport is correctly configured, you simply have the serial port closed loop, everything you send should receive, If you do not receive anything you have a serial port configuration problem
Related
I have created winform application to send SMS using USB modem, it working properly but I want to get the delivery message and confirm the message has been sent correctly.
Here is my program
private void button1_Click(object sender, EventArgs e)
{
try
{
SerialPort sp = new SerialPort();
sp.PortName = textBox1.Text;
sp.Open();
sp.WriteLine("AT" + Environment.NewLine);
Thread.Sleep(100);
sp.WriteLine("AT+CMGF=1" + Environment.NewLine);
Thread.Sleep(100);
sp.WriteLine("AT+CSCS=\"GSM\"" + Environment.NewLine);
Thread.Sleep(100);
sp.WriteLine("AT+CMGS=\"" + mobile + "\"" + Environment.NewLine);
Thread.Sleep(100);
sp.Write(message);
Thread.Sleep(100);
sp.Write(new byte[] { 26 }, 0, 1);
Thread.Sleep(100);
var response = sp.ReadExisting();
if (response.Contains("ERROR: 500"))
{
MessageBox.Show("Please check credits");
}
sp.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
Please help me how to read the delivery status with above code
This question is not C# specific; rather it's an AT commands question.
After sending a SMS, you'll get a response from modem, something likee this:
+CMGS: {sms id, 0 to 255}
OK
In this case, if Service Center has delivered the SMS successfully, modem will return this response:
+cds: {some id which does not matter} {PDU status report}
You need just decode this PDU to obtain status report, ID of original SMS and other useful data. If the ID of the sent SMS and the one from status report are equal, you have status report exactly for your message.
Note: if you remove message from modem's storage before receiving of delivery report, you'll get report which will be containing all usual information, but status of delivery will be most likely 71 instead of 0.
I used this approach myself, based on this answer, and it works.
Edit 1 :
you are handling the RS232 reading synchronously, which i dont really recomand,the reading function should be fired automatically when the data are available in the port,something like that :
private string SerialDataReceived = string.Empty
private void button1_Click(object sender, EventArgs e)
{
// new instance of the COM port
port = new SerialPort(ComPort, 115200, Parity.None, 8, StopBits.One);
// start port lessener
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications and wait for nad to reboot completly
port.Open();
//send your AT Commands
port.Write("ATE0\r\n");
// check the response 'if Command is successfull it reply with something +Ok'
if(SerialDataReceived.ToLower().Contains("ok"))
}
//event will be fired each time a new data are available in the port
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
SerialDataReceived += port.ReadExisting();
}
now in your send function you should check if you have in the end a response containing +CMGS:,
var response = sp.ReadExisting();
while (!response.Contains("OK") && !response.Contains("ERROR"))
{
// check if message has been sent before exiting
response = sp.ReadExisting();
}
I am trying to read 3 temperature devices using WinForms and the Modbus 485 protocol.
Basically I have to periodically write a command to each device, wait for response and when I get the response, process it. Each device has a unique communication adress. In order to periodically send the command I am using a timer.Timer1.interval=100;
This is how I am sending the command and where I am processing the response:
private void ProcessTimer_Tick(object sender, EventArgs e)
{
switch (tempState)
{
case TempTimerState.sendCommDevice1:
if (!tempSerial.IsOpen)
{
tempSerial.Open();
}
tempSerial.DiscardInBuffer();
communication.tempCommand[0] = 0x01; //device adress
communication.tempCommand[6] = 0xA5; //CRC
communication.tempCommand[7] = 0xC2; //CRC
tempSerial.Write(communication.tempCommand, 0, 8);
tempState = TempTimerState.recievedDevice1;
communication.waitTime = 0; //time to wait before throw a timeout exception
communication.dataRecievedTemp = false; //flag for response recieved
break;
case TempTimerState.recievedDevice1:
communication.waitTime++;
if (communication.dataRecievedTemp)
{
communication.waitTime = 0;
if(CheckCRC(communication.tempResponse)) //CRC checking
{
//process response
}
else
{
//handle CRC Failure error
}
}
if(commcommunication.waitTime>=maxWaitTime)
{
//handle Timeout exception
}
tempState=TempTimerState.sendCommDevice2;
break;
}
}
and so on for each device. This is my serialport data recieved event:
private void tempSerial_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
sp.Read(communication.tempResponse, 0, sp.BytesToRead);
communication.dataRecievedTemp = true; //flag for data recieved
}
So my communication should be :
send command device1
recieve response device1
send command device2
recieve command device2
send command device3
recieve command device3
and then send command device1 again. The problem is that I get sometimes get communication timeout error and I know for sure that all the devices are responding very quick and every time. Since I had preset the sp.ReceivedBytesThreshold=8I started to get CRC errors too. My response should always be 8 bytes long.
I think the problem is in the serial port data recieved event, but I can't see what's the problem.
P.S. I have also tried to set the timer interval to 1000 miliseconds, but that didn't solve my problem
Relying on ReceivedBytesThreshold is very brittle, the show is over when you get out of sync once. Your code is also very vulnerable to other reasons that DataReceived may fire, you are not checking the e.EventType property. Which certainly can be SerialData.Eof for a binary protocol.
Just write robust code that doesn't depend on the EventType nor the number of available bytes. Like this:
private byte[] rcveBuf = new byte[8];
private int rcveLen;
private void tempSerial_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
rcveLen += sp.Read(rcvebuf, rcveLen, rcveBuf.Length - rcveLen);
if (rcveLen == rcveBuf.Length) {
Array.Copy(rcveBuf, communication.tempResponse, rcveBuf.Length);
communication.dataRecievedTemp = true;
rcveLen = 0;
}
}
And reset rcveLen back to zero on a timeout. And make sure that the timeout isn't too low, you can lose many seconds if your program got swapped out, use 10 seconds to be safe.
I have an Arduino XBee shield and I have a Sparkfun XBee USB explorer. I would like to send data (temperature sensor) that comes from the Ardunio XBee and receive it in my C# programme.
For now, let's say I want to send 45, 100 to my C# programme.
I don't receive any data that comes from the XBee shield. Am I missing anything with the code?
The below code is the sender from the Arduino XBee shield:
SoftwareSerial mySerial(4,5);
void setup()
{
mySerial.begin(9600);
}
void loop()
{
if (mySerial.available() > 0)
{
mySerial.write(45);
mySerial.write(',');
mySerial.write(100);
mySerial.write('\n');
}
}
Receiver code for the USB XBee explorer in C#:
SerialPort port = new SerialPort();
public Form1()
{
try
{
port.PortName = "COM8";
port.BaudRate = 9600;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();
Console.WriteLine("Opened");
}
catch(Exception ex)
{
Console.WriteLine("Sorry! " + ex);
}
// Handler for receiving data
port.DataReceived += serialPort1_DataReceived;
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (port.IsOpen == true)
{
string RxString = port.ReadLine();
Console.WriteLine(RxString);
}
}
The XBee configuration:
One XBee is: Coordinator AT mode -- connected to USB Sparkfun Explorer
Another XBee is: Router AT mode -- Connected to Arduino shield
As tomlogic answered my question in Stack Overflow question XBee two-way communication (sender and receiver) at the same time.
I got it working. The problem was from my void loop() method. The mySerial should be like
mySerial.println(temperature);
However, you must check mySerial Rx,Tx pin that they are right one
Your XBee shield uses pins 0 and 1 on the Arduino. Softwareserial is not needed, just use:
Serial.begin(9600); // In void setup() routine
To send the temperature, use this in function loop:
Serial.print(temperature); // Need a variable 'temperature' of course...
Test the Arduino code with the built-in terminal in the Arduino IDE to see if the port actually can receive and send (remove the XBee shield first). After that works, test out the XBee communication.
Not a whole lot to say here other than this doesn't work, and I have no idea why.
The serial output on the Arduino is nothing. The output on the C# code goes down to waiting for a response and then nothing.
The Bluetooth card LED on the Arduino goes green when I start the C# program so there is a connection being made. Just nothing else.
Arduino Code
#include <SoftwareSerial.h> //Software Serial Port
#define RxD 8 // This is the pin that the Bluetooth (BT_TX) will transmit to the Arduino (RxD)
#define TxD 7 // This is the pin that the Bluetooth (BT_RX) will receive from the Arduino (TxD)
SoftwareSerial blueToothSerial(RxD,TxD);
boolean light = false;
void setup(){
Serial.begin(9600); // Allow Serial communication via USB cable to computer (if required)
pinMode(RxD, INPUT); // Setup the Arduino to receive INPUT from the bluetooth shield on Digital Pin 6
pinMode(TxD, OUTPUT); // Setup the Arduino to send data (OUTPUT) to the bluetooth shield on Digital Pin 7
pinMode(13,OUTPUT); // Use onboard LED if required.
}
void loop(){
delay(1000);
if(light){
light = false;
digitalWrite(13,LOW);
}
else{
light = true;
digitalWrite(13,HIGH);
}
//Serial.println(blueToothSerial.available());
blueToothSerial.write("Im alive");
if(blueToothSerial.read()>0){
Serial.write(blueToothSerial.read());
}
}
Core C# Code
static void Main(string[] args)
{
byte[] Command = Encoding.ASCII.GetBytes("It works");//{0x00,0x01,0x88};
SerialPort BlueToothConnection = new SerialPort();
BlueToothConnection.BaudRate = (9600);
BlueToothConnection.PortName = "COM4";
BlueToothConnection.Open();
if (BlueToothConnection.IsOpen)
{
BlueToothConnection.ErrorReceived += new SerialErrorReceivedEventHandler(BlueToothConnection_ErrorReceived);
// Declare a 2 bytes vector to store the message length header
Byte[] MessageLength = { 0x00, 0x00 };
//set the LSB to the length of the message
MessageLength[0] = (byte)Command.Length;
//send the 2 bytes header
BlueToothConnection.Write(MessageLength, 0, MessageLength.Length);
// send the message itself
System.Threading.Thread.Sleep(2000);
BlueToothConnection.Write(Command, 0, Command.Length);
Messages(5, ""); //This is the last thing that prints before it just waits for response.
int length = BlueToothConnection.ReadByte();
Messages(6, "");
// retrieve the reply data
for (int i = 0; i < length; i++)
{
Messages(7, (BlueToothConnection.ReadByte().ToString()));
}
}
}
Okay so there were a few issues that are hard to see from above so I will attempt to explain.
First, RX and TX on the bluetooth card DO NOT go to their equals on the arduino. They go to their opposites.
Example:
Bluetooth Card RX -> TX on Arduino
Bluetooth Card TX -> RX on Arduino
So if you look in the photo of the Arduino above it should be painfully obvious that pins 7 and 8 are the incorrect placement.
The next issue that I was having was poor connectivity.
The power and ground seem to be fine in the above configuration. However, the RX and TX connections need to be soldered in. Otherwise you get a poor connection.
Once I made this changes the above code worked flawlessly.
Hope this helps anyone else having these issues!!
Here is similar code simplified for testing the PC <-> Arduino BT communication. In the code below, the PC sends text to the Arduino, which then echoes it back to the PC. PC writes the incoming text to console.
Set your BT serial port (COM5 in the example) from Windows.
Tested with Arduino Uno, an USB-Bluetooth dongle and the bluetooth module HC-05. Arduino's PIN1(TX) voltage was divided from 5V to 2.5V before feeding it to the module's RX pin).
That's it. Easy!
Arduino:
void setup() {
Serial.begin(9600);
delay(50);
}
void loop() {
if (Serial.available())
Serial.write(Serial.read()); // echo everything
}
C#:
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
public class SerialTest
{
public static void Main()
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 9600;
serialPort.PortName = "COM5"; // Set in Windows
serialPort.Open();
int counter = 0;
while (serialPort.IsOpen)
{
// WRITE THE INCOMING BUFFER TO CONSOLE
while (serialPort.BytesToRead > 0)
{
Console.Write(Convert.ToChar(serialPort.ReadChar()));
}
// SEND
serialPort.WriteLine("PC counter: " + (counter++));
Thread.Sleep(500);
}
}
}
Im trying to read the output of a device on a COM port on my PC.
Im wrote a C# program to do so.
Using PuTTY, I can see the output Im expecting from my device.
The problem is that the function SerialPort.ReadExisting(); in my DataReceived function gives my a completely different string.
What is the proper way to read from a COM port using SerialPort?
Also, the strings I get from SerialPort.ReadExisting(); are fragments of the string I sent to the device.
Below is the code that initializes the SerialPort.
SerialPort port;
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = port.ReadExisting();
}
void init_serialport(object sender, EventArgs e)
{
if (port != null)
{
port.Close();
}
port = new SerialPort( /* ... */ );
port.BaudRate = 9600;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Handshake = Handshake.RequestToSend;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
try
{
port.Open();
}
catch (Exception ex)
{
// ...
}
}
the strings I get from SerialPort.ReadExisting(); are fragments of the string I sent to the device.
I'd have a look at SerialPort.ReceivedBytesThreshold.
"Gets or sets the number of bytes in the internal input buffer before a DataReceived event occurs."
I would first take a look at the Read method of the port object, look at the raw bytes and verify that they match your expectations, which would then narrow down the problem to the encoding on the conversion to string.
More information on this is provided here.
You received fragments because SerialPort.Existing() executes and completes in less time then it takes for your sending device to send the entire string.
You need to repeat the call continuously or until you received the end of string character if the string has one.