How to execute command by plugging arduino to USB - arduino

The idea is:
Connect arduino to PC via USB port (Windows 7, administrator logged
in)
System automatically execute command (for example: shutdown -s
-t 3600)
Is it possible to make that without using proxy application on host?

Here are two code snippets that address the fundamentals of this question. First, is a sketch that issues a "DIR" command. Obviously, this could be any command.
#include <stdio.h>
uint8_t command[] = "dir\0";
void setup()
{
Serial.begin(9600);
delay(10000);
Serial.write(command, 4);
}
void loop() {}
Second, is C code that reads COM5 and after receiving a string issues a command.
/*
* main.c
*
* Created on: Sep 29, 2013
* Author: Jack Coleman
*
* This software is for demonstration purposes only.
*
*/
#include <stdio.h>
#include <Windows.h>
//
// create a console that accepts data
// from a com port and issues it as system commands.
//
void display_config(COMMCONFIG *config_comm)
{
printf("BaudRate = ");
switch (config_comm->dcb.BaudRate)
{
case CBR_9600 : printf("9600\n");
}
printf("Parity = %d\n", config_comm->dcb.Parity);
printf("StopBits = %d\n", config_comm->dcb.StopBits);
printf("ByteSize = %d\n", config_comm->dcb.ByteSize);
fflush(stdout);
}
main() // Version 0
{
HANDLE hCOM5;
int config_size;
COMMCONFIG config_comm;
int retc;
int nr_read;
char *comm_char;
char sysline[271];
hCOM5 = CreateFile("COM5", GENERIC_READ, 0, 0,
OPEN_EXISTING, 0, NULL);
if (hCOM5 <= 0)
{
printf("unable to open COM5");
return;
}
GetCommConfig(hCOM5, &config_comm, &config_size);
config_comm.dcb.BaudRate = CBR_9600;
config_comm.dcb.Parity = NOPARITY;
config_comm.dcb.StopBits = ONESTOPBIT;
config_comm.dcb.ByteSize = 8;
retc = SetCommConfig(hCOM5, &config_comm, config_size);
if (retc == 0)
{
printf("SetCommConfig failed.\n");
return;
}
display_config(&config_comm);
// wait here for a possible, initial
// series of 0xFF.
comm_char = sysline;
do
{
ReadFile(hCOM5, comm_char, 1, &nr_read, NULL);
printf("%x nr_read = %d\n", *comm_char, nr_read);
fflush(stdout);
} while (nr_read == 0);
while (nr_read == 1)
{
if (*comm_char == 0x00)
{
printf("%s\n", &sysline[0]);
fflush(stdout);
system(&sysline[0]);
break;
} else {
comm_char++;
}
ReadFile(hCOM5, comm_char, 1, &nr_read, NULL);
printf("%02x\n", *comm_char);
fflush(stdout);
}
return;
}
This was a fun little coding problem. Several lessons were learned: 1) when communicating via a serial line, the C program will simply wait until the first byte is transmitted by the Arduino. There are no syncing chars to preface the data transmission (that is, if there are any they get stripped out by the system code); 2) It is possible to get zero (0) for the number of bytes read.
Could this be used to use an Arduino to issue a shut down command? Yes, but the program would have to be started (i.e. scheduled) and then it would wait for the Arduino to speak.

Related

Receiving data from SIM808

I am trying to use SIM808 module but I have no response even after sending only "AT". I am using 5V/2.5A AC/DC adapter. The board (ecb-v3.2) is rather connected well because two diodes are on all the time and one is blinking every three seconds. I tried my UART code by sending and receiving data from uC to PC and it worked. I also tried to display some data in different parts of my code to find a line with a bug. I think that problem is in the while loop in which I am waiting for receiving a single char from SIM808 module. I marked this line in the code (in function UART_RxChar()). I am using two UARTs in my code, one for sending data between uC and PC (channel 0 in the code) and second for sending data between uC and SIM808 (channel 1), but I checked both versions on my computer. This is my code:
#define F_OSC 7372800UL
#define BAUD 115200
#define ubrr ((F_OSC/16/BAUD)-1)
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
void UART_TxString(char *string_ptr, uint8_t channel);
void UART_Init( uint8_t channel )
{
if ( channel == 0)
{
/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/*Enable receiver and transmitter */
UCSR0B = (1<<TXEN0) | (1<<RXEN0);
/* Set frame format: 8data, 1stop bit */
UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
}
else
{
/*Set baud rate */
UBRR1H = (unsigned char)(ubrr>>8);
UBRR1L = (unsigned char)ubrr;
/*Enable receiver and transmitter */
UCSR1B = (1<<TXEN1) | (1<<RXEN1);
/* Set frame format: 8data, 1stop bit */
UCSR1C = (1<<UCSZ10)|(1<<UCSZ11);
}
}
char UART_RxChar( uint8_t channel )
{
if ( channel == 0 )
{
while((UCSR0A & (1<<RXC0))==0); // Wait till the data is received
return(UDR0); // return the received char
}
else
{
//Here is the problem. The condition in the loop is always true.
while((UCSR1A & (1<<RXC1))==0); // Wait till the data is received
return(UDR1); // return the received char
}
}
void UART_TxChar(char ch, uint8_t channel)
{
if ( channel == 0)
{
while((UCSR0A & (1<<UDRE0))==0); // Wait till Transmitter(UDR) register becomes Empty
UDR0 =ch; // Load the data to be transmitted
}
else
{
while((UCSR1A & (1<<UDRE1))==0); // Wait till Transmitter(UDR) register becomes Empty
UDR1 =ch; // Load the data to be transmitted
UART_TxChar(ch,0);
}
}
void UART_TxString(char *string_ptr, uint8_t channel)
{
while(*string_ptr)
UART_TxChar(*string_ptr++, channel);
}
void UART_RxString(char *string_ptr, uint8_t channel)
{
char ch;
while(1)
{
ch=UART_RxChar(channel); //Reaceive a char
UART_TxChar(ch, channel); //Echo back the received char
if((ch=='\r') || (ch=='\n')) //read till enter key is pressed
{ //once enter key is pressed
*string_ptr=0; //null terminate the string
break; //and break the loop
}
*string_ptr=ch; //copy the char into string.
string_ptr++; //and increment the pointer
}
}
int main(void)
{
UART_Init(0);
UART_Init(1);
initLCD();
UART_TxString("\r\nstart", 0);
while(1)
{
char ans[15] = "";
DDRE = 0xff;
UART_TxString("AT\r\n",1);
DDRE = 0x00;
UART_RxString(ans,1);
_delay_ms(2000);
}
}
I also checked all possibilities sending: AT\r", "AT\n", "AT\r\n", "AT\n\r.
Thank you in advance for any help.
The problem is you are echoing the received character back to SIM808 module on line
UART_TxChar(ch, channel); //Echo back the received char
this may confuse SIM808 and put it in inconsistent state.
Try connecting SIM808 module to PC and use CoolTerm to analyze response after firing AT command.

Serial communication on STM32F303 using HAL - Rx not working

I am using an STM32F303RE Nucleo board connected to my own PCB to do RS-232 serial communications, and I can't figure out why this code doesn't work in certain circumstances.
I'm using HAL functions (HAL_UART_Transmit and HAL_UART_Receive) for my communications, using the USB connector on the Nucleo for usart2 and a 9-pin RS-232 serial port on my own PCB for usart1. Both usart configurations have been set up by HAL.
When I communicate (using a Putty terminal) using only the USB connection (usart2), the code works perfectly. When I use usart1 for Tx and usart2 for Rx, still no problems. When I use usart2 for Tx and usart1 for Rx, it also works fine.
The problem is when I try to use usart1 (which is my RS-232 cable) for both Tx and Rx. My processor transmits the initial data fine, but when it's time to receive the data, nothing makes it into the received data register. I have some code to simply echo back any received data on the transmit line, and nothing comes through in this configuration. Once again - the code works fine in every other configuration of usart1 and usart2 for both sending and receiving, but no Rx when I try to do it all on usart1 (RS-232)
Here is the relevant section of code I'm using. COMTYPE is set to either &huart1 or &huart2 (in the problem case, it's set to &huart1)
Main loop (received data used for switch statement in menu system):
HAL_UART_Transmit(COMTYPE, prompt, sizeof(prompt), TIMEOUT);
cmd_size = UART_getstr(command);
cmd_num = parse_menu_input(command, cmd_size);
converted = (uint8_t)cmd_num + '0';
// error parsing command for menu selection
if(cmd_num == -1){
HAL_UART_Transmit(COMTYPE, parse_error, sizeof(parse_error), TIMEOUT);
}
else{
menu_switch(cmd_num);
}
}
Function containing Rx function and echo back (Tx) function:
int UART_getstr(uint8_t* command){
int x = 0; // tracker for buffer pointer
int chars = 0;
uint8_t buffer; // single char storage for UART receive
while(1){
// get single char from UART_Receive
HAL_UART_Receive(COMTYPE, &buffer, 1, HAL_MAX_DELAY);
// echo back function
HAL_UART_Transmit(COMTYPE, &buffer, sizeof(char), TIMEOUT);
// write value of received char to "command" array
command[x] = buffer;
// increment the number of valid chars
chars++;
// stop adding chars to command after [Enter] pressed
if(command[x] == '\r'){
chars--;
break;
}
// correct for storing DELETE as char in buffer
if(command[x] == 0x7F){
command -= 1;
chars -= 2;
}
else{
x++;
}
}
command[x] = '\0';
// return length of command buffer
return chars; }
I don't understand why the exact same code would work in 3 out of 4 circumstances, but not the 4th. I've checked the serial cable, and the rest of the RS-232 hardware functions fine when being used ONLY for Tx or ONLY for Rx. But the Rx seems blocked by something when trying to use RS-232 for both.
EDIT: Adding UART initialization code (generated by HAL):
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* USART2 init function */
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}

Can read, but cannot write serial ports on Ubuntu 16.04

I have a strange problem with trying to write data to a serial port.
I am running Ubuntu 16.04 on a NUC7i7DNBE, and am trying to make a serial connection to an Arduino UNO. The Serial API that I am using is found here: http://docs.ros.org/kinetic/api/serial/html/classserial_1_1Serial.html
I have written a simple program which opens the serial port "ttyACM0" to communicate with the arduino. I have tested this code on another computer running Ubuntu 16.04, and everything worked fine, the only permissions I had to set where adding the user to the dialout group.
On the NUC, however, I have added the user to the dialout group. This allowed the program to read from the Arduino, but it still does not write to the Arduino. The Arduino IDE will write to the Arduino just fine, but my program will not.
I am assuming that I am having trouble with serial write permissions in Ubuntu.
Steps I have taken:
I have added the user to the dialout group
I have added a rule in /etc/udev/rules.d/ which states:
SUBSYSTEMS=="tty", GROUP="dialout", MODE="0666"
Afterward, I sent the commands:
sudo chown root:root /etc/udev/rules.d/50-AVCusb.rules
sudo chmod 0644 /etc/udev/rules.d/50-AVCusb.rules
udevadm control --reload-rules
I followed some information found on stack exchange to get to this point:
https://unix.stackexchange.com/questions/111593/allow-non-root-user-to-read-write-dev-files
I have tried using an FTDI device to write to the Arduino port. The FTDI device uses the ttyUSB0 port rather than the ttyACM0 port. The result was the same; can read, but can't write.
I have also run my external hard-drive on the NUC to see if there was any kind of hardware issue. When I ran the program from my external hard drive, I had no problem reading from and writing to the Arduino.
I have not dealt much with Ubuntu permissions or ports in general, please help me find and upload any other information that you may need in order to help me solve this problem.
Code on NUC:
#include <ros/ros.h>
#include <serial/serial.h>
using namespace serial;
Serial ser;
static const uint8_t MOTOR_ID = 0;
void writeMotor(uint8_t byte)
{
size_t size = 4;
uint8_t buffer[size];
buffer[0] = 'G'; //PID
buffer[1] = 'O';
buffer[2] = MOTOR_ID; //address
buffer[3] = byte; //data byte
ser.write(buffer, size);
}
int main() {
ros::init(argc, argv, "servo_esc_driver");
std::string port = "/dev/ttyACM0";
Timeout timeout = Timeout(0, 0, 0, 0, 0);
bytesize_t bytesize = eightbits;
parity_t parity = parity_none;
stopbits_t stopbits = stopbits_one;
flowcontrol_t flowcontrol = flowcontrol_none;
try{
ser.setPort(port);
ser.setBaudrate(115200);
ser.setTimeout(timeout);
ser.setBytesize(bytesize);
ser.setParity(parity);
ser.setStopbits(stopbits);
ser.setFlowcontrol(flowcontrol);
ser.open();
}
catch (SerialException e) {
ROS_FATAL_NAMED("Failed to connect to the Arduino UNO, %s.", e.what());
ros::shutdown();
return 0;
}
uint8_t byte = 90;
writeMotor(byte);
}
Full Code on Arduino
#include <Servo.h>
const byte N = 2;
//Servo esc;
//Servo servo;
Servo servo[N];
//int escPos = 90;
//int servoPos = 90;
int pos[N];
static const byte ESC_PIN = 7;
static const byte SERVO_PIN = 8;
static const byte RPM_FEEDBACK_PIN = 0; //interrpt 0, pin 2
static const byte SERVO_FEEDBACK_PIN = A0;
//const float MUL = 0.7058823529; //180/255
unsigned long lastTime_servoFeedback = 0;
static const byte MOTOR_ID = 0; //ID for differentiating data received and sent over serial connections
static const byte SERVO_ID = 1;
//added for motor data timeout safety feature
static const unsigned long MOTOR_DATA_TIMEOUT = 200; //4 x 50 ms (50 ms time period expected)
static unsigned long lastTimeMotorData = 0;
static const byte NEUTRAL = 90;
unsigned long last_rpm_pulse_update_ms = 0; //used for detecting a stopped car, and rejecting old data when writing to the serial port
unsigned long last_rpm_pulse_time_us = 0;//keeps track of rpms by comparing to system timer
static const long REV_PERIOD_MAX_US = 100000; //in us
unsigned long rev_period = REV_PERIOD_MAX_US; //100 ms is considered too long to be in motion
boolean forward = true;
/*Scratch that, I want these parameters set in ROS:
static const float wheel_radius = 0.05 // meters
static const float revs_to_mps_MUL = //assuming 2.85 gear ratio for brushless motor differential: https://forums.traxxas.com/showthread.php?9080733-Diff-gear-ratios
*/
//boolean rpm_period_updated = false; //rpms must be updated every 100 ms, otherwise the car has stopped, and velocity data should show 0 m/s
void rpm_feedback()
{
//Serial.println("in rpm_feedback");
last_rpm_pulse_update_ms = millis(); //notice the 'ms' here we want to use millisecond for checking whether or not data is valid. millis() can count up to 50 days while micros() only counts up to 70 minutes, thus millis() is used here.
unsigned long time_now = micros(); //use time now for accurate time calculations
unsigned long rev_period_temp = time_now - last_rpm_pulse_time_us; //get spur-gear revolution period
if(rev_period_temp > 0) rev_period = rev_period_temp; //revs are within
else rev_period = REV_PERIOD_MAX_US;
last_rpm_pulse_time_us = time_now; //using 'time_now' ensures that the time taken to get to this point in code does not interfere with rev_period accuracy - - - micros(); //reset time
if(pos[MOTOR_ID] < 90) //determine the direction that the vehicle is traveling in
{
forward = false;
}else forward = true;
//rpm_period_updated = true; not needed, only last_rpm_pulse_time_ms is needed for checking
}
void setup() {
// put your setup code here, to run once:
pinMode(RPM_FEEDBACK_PIN, INPUT_PULLUP);
attachInterrupt(RPM_FEEDBACK_PIN, rpm_feedback,FALLING); //arduino reference recommends using digitalPinToInterrupt(RPM_FEEDBACK_PIN) but the command is not recognized here
analogReference(EXTERNAL); //Using external reference for servo position
for(int i = 0; i < N; i++) //initialize
{
pos[i] = 90;
servo[i].attach(ESC_PIN + i);
}
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() >= 1)
{
if(Serial.read() == 'G')
{
unsigned long t = millis();
while((Serial.available() < 3) && ((millis() - t) < 10)); //wait for the rest of the package, or timeout
if(Serial.available() >= 3)
{
char buf[3];
Serial.readBytes(buf, 3);
if((buf[0] == 'O') && (buf[1] >= 0) && (buf[1] < 2))
{
pos[buf[1]] = byte(buf[2]);
if(buf[1] == MOTOR_ID) lastTimeMotorData = millis(); //time stamp of last motor data retrieval
//Serial.print("buf[2]: ");
//Serial.println(byte(buf[2]), DEC);
//Serial.print("pos: ");
//Serial.println(pos[buf[1]]);
}
}
}
}
if((millis() - lastTimeMotorData) > MOTOR_DATA_TIMEOUT) pos[MOTOR_ID] = NEUTRAL; //stop the motor if data is not being received
for(int i = 0; i < N; i++)
{
servo[i].write(pos[i]);
}
if((millis() - lastTime_servoFeedback) >= 50) // 20Hz 20) //50Hz matches current ROS driver settings
{
lastTime_servoFeedback = millis();
int servo_feedback = analogRead(SERVO_FEEDBACK_PIN);
Serial.write('G'); //PID
Serial.write('O');
Serial.write(SERVO_ID);
//Serial.print(servo_feedback);
Serial.write(lowByte(servo_feedback));
Serial.write(highByte(servo_feedback));
//Serial.println(servo_feedback);
float rev_frequency;
if((last_rpm_pulse_update_ms + 100) < millis()) rev_frequency = 0; //use millis() since it can count up to 50 days, and will not have a chance of a hiccup after 70 minutes of using micros()
//instead, correct period when slowing down, also stop when the maximum threshold is reached
//if((micros() - last_rpm_pulse_time_us) >= REV_PERIOD_MAX_US) rev_frequency = 0; //car is stopped in this case. I decided not to try correcting the period as mentioned above
else rev_frequency = (float) 1/rev_period*1000000;
byte *rev_freq_bytes_to_transmit = (byte *) &rev_frequency;
if(forward == false) rev_frequency = -rev_frequency; //a negative frequency is used for reverse
Serial.write('G'); //PID
Serial.write('O');
Serial.write(MOTOR_ID); //used for addressing
Serial.write(rev_freq_bytes_to_transmit, 4);
}
}
Some good information may be:
snuc#usuavc:~$ udevadm info -a -n /dev/ttyACM0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/tty/ttyACM0':
KERNEL=="ttyACM0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0':
KERNELS=="1-4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="cdc_acm"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="02"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="01"
ATTRS{bInterfaceSubClass}=="02"
ATTRS{bNumEndpoints}=="01"
ATTRS{bmCapabilities}=="6"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4':
KERNELS=="1-4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="02"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="100mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bcdDevice}=="0001"
ATTRS{bmAttributes}=="c0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="4"
ATTRS{devpath}=="4"
ATTRS{idProduct}=="0043"
ATTRS{idVendor}=="2341"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Arduino (www.arduino.cc)"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{serial}=="55330313635351207081"
ATTRS{speed}=="12"
ATTRS{urbnum}=="6990"
ATTRS{version}==" 1.10"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.15.0-32-generic xhci-hcd"
ATTRS{maxchild}=="12"
ATTRS{product}=="xHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:14.0"
ATTRS{speed}=="480"
ATTRS{urbnum}=="76"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{d3cold_allowed}=="1"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0x9d2f"
ATTRS{dma_mask_bits}=="64"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="122"
ATTRS{local_cpulist}=="0-7"
ATTRS{local_cpus}=="ff"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x21"
ATTRS{subsystem_device}=="0x2070"
ATTRS{subsystem_vendor}=="0x8086"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
I decided that the problem was with the ROS version of serial. I decided to try some native linux library, termios, and had success writing to the port!
I found this example code:
https://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux
The problem lies in the ros serial installation somehow.
Don't know if you still want to solve this with serial/serial.h, but I think that your problem might be in the timeout settings.
I'm telling you this, 'cause I had the exact same problem, I could read the incoming data, but couldn't write.
The /dev/ttyUSB0 permission was ok, but not the timeout.
I found the following config on internet, gave a try and work. Now I can read and write.
try{
ser.setPort("/dev/ttyUSB0");
ser.setBaudrate(9600);
serial::Timeout to = serial::Timeout::simpleTimeout(10);
ser.setTimeout(to);
ser.open();
return true;
}
catch (SerialException e) {
return 0;

How to take data from gps then send to my phone in arduino

I want to do project which will use GPS & GSM module, use Arduino, take data from GPS(GY-GPS/NEO6MV2) and send by GSM(SIM900 GSM/GPRS Module ) to my phone. I am using separate GPS module
I try this code but still have problem.
#include <SoftwareSerial.h>
#include "SIM900.h"
#include <TinyGPS.h>
#include "sms.h"
SMSGSM sms;
TinyGPS gps;
SoftwareSerial ss(4, 3);
SoftwareSerial SIM900(7, 8);
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
String strL, strN, message, textForSMS;
char charL[10], charN[10], text[200];
int m = 1;
boolean started = false;
void setup()
{
Serial.begin(9600);
ss.begin(9600);
gsm.begin(9600);
}
void loop()
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
gps.f_get_position(&flat, &flon, &age);
textForSMS = "Moosa Home"; //testing gps from here
Serial.println(textForSMS);
Serial.println(flat, 6);
Serial.println(flon, 6);
Serial.print("longitude: ");
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
Serial.println("");
Serial.print("latitude : ");
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
smartdelay(1000);
Serial.println(""); //till here
delay(1000);
if (m == 5) //send sms on third reading
{
Serial.println("XXXXXXXXX"); //to check whether 'if' works
dtostrf(flat, 4, 6, charL);
for (int i = 0; i < 10; i++)
{
strL += charL[i];
}
dtostrf(flon, 4, 6, charN);
for (int i = 0; i < 10; i++)
{
strN += charN[i];
}
message = "Home";
message = message + "/nLat: ";
message = message + strL;
message = message + "/nLon: ";
message = message + strN;
message.toCharArray(text, 250);
Serial.println(text);
if (sms.SendSMS("+999999999999999", text))
{
Serial.println("\nSMS sent OK.");
}
else
{
Serial.println("\nError sending SMS.");
}
do {} while (1);
}
m++;
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs( val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i = flen; i < len; ++i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i = 0; i < len; ++i)
Serial.print(i < slen ? str[i] : ' ');
smartdelay(0);
}
I receive SMS
Home/nLat:1000.00000/nLon:1000.00000`
where is my mistake in this code?
I am sure Gps & gsm work properly
Using TinyGPS on SoftwareSerial + a loop() structure using delay(1000), has very low odds of working. The m counter is really useless here, because loop() will execute 1000's of times while the GPS characters are arriving. And doing a get_position is useless, because you may not have any GPS data yet.
Basically, loop() should be constantly running, without delays. When something important happens (like getting all of a GPS sentence, or enough time has passed), that's when you do your other work (like send an SMS message). The TinyGPS smartDelay is not smart.
You should restructure the loop to look more like this example from the NeoGPS library. All the non-GPS work should be performed where the digitalWrite is in that example (line 62). That's where you would take the time to send an SMS.
The TinyGPS examples would require a complete rewrite to do what you want. They are fine by themselves, but it is difficult to extend them to do other things, like send an SMS. As I said, the loop structure must change.
I suggest taking a look at the NeoGPS library I wrote, as the examples are more robust. The library also uses much less RAM and CPU time, but that isn't a big problem if all you need to do is send an SMS message. If you do want to try it, be sure to review the default SoftwareSerial choice.
If you get the simple NMEAblink.ino example to work, I would suggest trying NMEA.ino. Then insert your code into the doSomeWork function. Most of what you have in loop needs to go in the doSomeWork function, which is called only when a complete RMC sentence is received.
Regardless of which library you use, you also need to check whether the data is valid. What if your GPS isn't receiving any satellites? It may still send an RMC sentence, but there won't be any lat/lon data. You probably shouldn't send an SMS if the location field is not valid.

Initializing Xbee S1 by an Arduino mini pro

I am trying to configurate my XBee module by an Arduino pro mini that is connected to my computer by de FTDI basic from sparkfun.
I already can write and send data from the Xbee to another Xbee module by the Arduino.
My problem is that I want to configure the Xbee by the arduino. I am sending ‘+++’ with the arduino to my Xbee and want to receive the ‘OK’ from the Xbee with the serial monitor from the arduino editor. The problem is that I can send it but never receive and ‘OK’, and when I am trying to configure the Xbee the configuration never happened. So I cant reach the Xbee command line.
uint8_t pinRx = 0, pinTx = 1; //Initialise pins on the Arduino
char GotChar;
long BaudRate = 4800;
int incomingByte=0;
SoftwareSerial mySerial( pinRx , pinTx ); //Initialise SoftwareSerial
void init_USB()
{
Serial.begin(BaudRate);
Serial.println("Start");
mySerial.begin(BaudRate);
}
void init_XBee()
{
Serial.begin(9600);
int check = 0;
while(T_XBEE_CONTROLLER_CheckOK() == 0)
{
Serial.println("CheckOK");
Serial.write("+++");
delay(2000);
}
Serial.println("ATCH 8\r");
delay(2000);
Serial.write("ATID 1234\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATPL 0\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATAP 2\r");
delay(2000);
}
int T_XBEE_CONTROLLER_CheckOK()
{
char ch[2];
ch[0] = 0x00;
while(! ((ch[0] == 'O' ) && (ch[1] == 'K') ))
{
ch[0] = mySerial.read();
ch[1] = mySerial.read();
if((ch[0] != 'O') && (ch[1] != 'K') && (ch[2] != '\r'))
{
Serial.println("FAILED");
return 0;
}
Serial.println("SUCCES");
return 1;
}
return 0;
}
it is a stupid answer but first of all, you should check that your Xbee is configured as AT device instead of API device. If it is API mode, the module wont understand the messages.
To do that you just have to use X-CTU application and read the configuration of the module, and change it to AT device.
Hope that helps.
Thanks for the response and the help, and also sorry for the late response.
I already solved the problem. The problem was the function write(). If you want to reach the command mode from the XBee you should only send "+++". If there is some kind of character behind the "+++" you can't reach the command line. The function write put a (for me) unknown character behing the "+++". So that's the problem for not reaching the command line.
To resolve this problem just use the function print("+++"). After using this function it is possible to reach the command line.
You have to read from the serial right after you send the +++ command, because this is where the xbee writes 'OK'. Also a better way to respect the guard times is to wait for a reply, and test to see if it is 'OK'.
Here is my code, I don't remember if it was working the last time I checked but I will just paste it here and you can modify it as you like. All it does is broadcast A1, B2, C3, etc.
There's a lot of commenting out where I was experimenting, but the regular comments are informative. Make sure you go through it step by step, it's quite simple when you get your head around it. Don't forget to change the destination address low to 0xFFFF if you want to broadcast.
In the end you'll come to the same realisation I did that AT mode is not suitable for configuring the xbee by writing programs.
For example I had an xbee constantly transmitting the number '2', and when another xbee was entering command mode using this code, it would receive the number 2 from the remote xbee when it should have received the 'OK' message from the local xbee, thus the program didn't acknowledge it being in command mode and breaking. When entering command mode you'd think an xbee would turn it's receiver off, but that's not the case so you can easily get into trouble.
If you want to do it the right way, have a look at API mode. I have series 1 xbee's so I'm implementing the Digimesh protocol, which so far I haven't seen anyone online do, but it's almost identical to the Zigbee so it's easy. If you'd like I can give you my code for that which can serve as a simple example.
/*
unicast_configure
Configure an XBee for unicast transmission and transmit
some characters to test
*/
#include <SoftwareSerial.h>
// Pins on Bees Shield:
SoftwareSerial xbee(2, 3); // TX, RX
boolean configured;
char c = 'A';
boolean configureRadio() {
// Set the data rate for the SoftwareSerial port:
xbee.begin(9600);
// Put the radio in command mode:
Serial.write("Entering command mode\r");
delay(1000);
while(xbee.available()>0) {xbee.read();}
xbee.write("+++");
while(xbee.available()>0) {xbee.read();}
//delay(1000);
//while(xbee.available() > 0) {Serial.write(xbee.read());}
String ok_response = "OK\r"; // The response we expect
// Read the text of the response into the response variable
// This satisfies the guard time by waiting for the OK message
String response = String("");
while (response.length() < ok_response.length()) {
if (xbee.available() > 0) {
response += (char) xbee.read();
}
}
Serial.println("response1: " + response);
// If we got received OK, configure the XBee and return true:
if (response.equals(ok_response)) {
Serial.println("Enter command mode successful");
// Restore to default values:
Serial.println("Restoring default values before making changes");
xbee.write("ATRE\r");
Serial.println("Setting addr high");
xbee.write("ATDH0\r"); // Destination high
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting addr low");
xbee.write("ATDL1\r"); // Destination low-REPLACE THIS
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting MY address");
xbee.write("ATMYFFFF\r");
// Apply changes:
Serial.println("Applying changes");
xbee.write("ATAC\r");
/*
///////////////////////////////////////////////
// Write to non-volatile memory:
// Use similar technique as above to satisfy guard time
Serial.write("Saving\r");
xbee.write("ATWR\r");
String response2 = String("");
//while (xbee.available() > 0) {Serial.write(xbee.read());}
while (response2.length() < ok_response.length()) {
if (xbee.available() > 0) {
response2 += (char) xbee.read();
}
}
Serial.println("response2: " + response2);
if (response2.equals(ok_response)) {
Serial.println("Save successful");
}
else { Serial.println("Save not successful");
return false;
}
// And reset module:
Serial.println("Resetting");
xbee.write("ATFR\r");
///////////////////////////////////////////////
*/
Serial.write("Exit command mode\r");
xbee.write("ATCN\r"); // Exit command mode
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.write("Finished\r");
return true;
} else {
return false; // This indicates the response was incorrect
}
}
void setup() {
Serial.begin(9600); // Begin serial
configured = configureRadio();
}
void loop() {
// Test transmission:
if (configured) {
xbee.print(c);
Serial.print(c);
c = c + 1;
if (c > 'Z') { c = 'A'; }
}
else {
Serial.println("Not configured (in loop)");
delay(5000);
Serial.println("Retrying configuration");
configured = configureRadio();
}
delay(1500);
}

Resources