I am trying to write the char "b" out the serial port on an iPhone using code example provided from this tutorial, but I am not getting the desired results. When I use the serial console app provided from this link it seems to be sending the letter / char "b" to the Arduino because my light starts blinking.
The method I constructed for the app that I am trying to send the "b" char looks like the following,
- (IBAction)blinkFlow_A_LED:(id)sender {
// method to blink the Flow_A LED on the kegboard-mini Arduino sheild.
NSLog(#"blink Flow_A btn pressed");
NSLog(#"hello kyle");
// open serial port / interface
[serial open:B2400];
if(serial.isOpened)
{
NSLog(#"Serial Port Opened");
}
else NSLog(#"Serial Port Closed");
// print serial debugging messages
serial.debug = true;
// send serial data (tx)
[serial write:text];
// print message sent
NSLog(#"the command sent was:%#",text);
}
Where are you defining 'text'? Text should be NSString.
Eg:
[serial write:#"hello world"];
Related
I build a code in Xcode console with C++ project works perfectly before:
#include "SerialPort.hpp"
#include "TypeAbbreviations.hpp"
#include <iostream>
int main(int argc, const char * argv[]) {
//* Open port, and connect to a device
const char devicePathStr[] = "/dev/tty.usbserial-A104RXG4";
const int baudRate = 9600;
int sfd = openAndConfigureSerialPort(devicePathStr, baudRate);
if (sfd < 0) {
if (sfd == -1) {
printf("Unable to connect to serial port.\n");
}
else { //sfd == -2
printf("Error setting serial port attributes.\n");
}
return 0;
}
// * Read using readSerialData(char* bytes, size_t length)
// * Write using writeSerialData(const char* bytes, size_t length)
// * Remember to flush potentially buffered data when necessary
// * Close serial port when done
const char dataToWrite[]="abcd";
char databuffer[1024];
while(1){
readSerialData(databuffer, 4);
sleep(2);
writeSerialData(databuffer, 4);
sleep(2);
}
printf("end.\n");
return 0;
}
After this build, I tried to migrate it to my Xcode cocoa application with C++ wrappers below.
I am pretty sure my Wrapper works fine with test C++ code. That means, I can call C++ function from my ViewController.swift.
But there's one strange thing happened. I am not able to open connection with the following code:
sfd = open(portPath, (O_RDWR | O_NOCTTY | O_NDELAY));
if (sfd == -1) {
printf("Unable to open serial port: %s at baud rate: %d\n", portPath, baudRate);
printf("%s", std::strerror(errno));
return sfd;
}
There error message returns :
Unable to open serial port: /dev/tty.usbserial-A104RXG4 at baud rate: 9600
Operation not permitted
I've tried to change app sandbox configuration, set up my system preference to grant access to my app, also I disabled my rootless. (csrutil disable with command + R)
But the problem still persists:
&
I want to ask that:
1. Why my code on Xcode C++ project works fine but fail on swift's cocoa app on Xcode?
2. How to solve the "Operation not permitted" Issue.
My Xcode version is 11.3.1 and Mac OS is 10.14.6 Mojave.
I figure it out myself.
It's APP sandbox is bothering me.
All you need to do is turn off sandbox
Turn off it by click X on the mouse point.
If you want to add it back, just click +Capability and put it back on.
https://i.stack.imgur.com/ZOc18.jpg
reference : https://forums.developer.apple.com/thread/94177#285075
I'm gonna to read/write under the modbus-tcp specification.
So, I'm trying to code the client and server in the linux environment.
(I would communicate with the windows program(as a client) using the modbus-tcp.)
but it doesn't work as I want, so I ask you here.
I'm testing the client code for linux as a client and the easymodbus as a server.
I used the libmodbus code.
I'd like to read coil(0x01) and write coil(0x05).
When the code is executed using the libmodbus, 'ff' is printed out from the Unit ID part.(according to the manual, 01 should be output for modbus-tcp.
I don't know why 'ff' is printed(photo attached).
Wrong result:
Expected result:
'[00] [00] .... [00]' ; Do you know where to control this part?
Do you have or do you know the sample code that implements the 'read/write' function using the libmodbus?
please let me know the information, if you know that.
ctx = modbus_new_tcp("192.168.0.99", 502);
modbus_set_debug(ctx, TRUE);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rq_bits, 0, nb * sizeof(uint8_t));
tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
nb_loop = nb_fail = 0;
/* WRITE BIT */
rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]);
if (rc != 1) {
printf("ERROR modbus_write_bit (%d)\n", rc);
printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]);
nb_fail++;
} else {
rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits);
if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) {
printf("ERROR modbus_read_bits single (%d)\n", rc);
printf("address = %d\n", addr);
nb_fail++;
}
}
printf("Test: ");
if (nb_fail)
printf("%d FAILS\n", nb_fail);
else
printf("SUCCESS\n");
free(tab_rq_bits);
free(tab_rp_bits);
/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);
return 0;
That FF you see right before the Modbus function is actually correct. Quoting the Modbus Implementation Guide, page 23:
On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the
MODBUS Unit Identifier is useless. The value 0xFF has to be used.
So libmodbus is just sticking to the Modbus specification. I'm assuming, then, that the problem is in easymodbus, which is apparently expecting you to use 0x01as the unit id in your queries.
I imagine you don't want to mess with easymodbus, so you can fix this problem pretty easily from libmodbus: just change the default unit id:
modbus_set_slave(ctx, 1);
You could also go with:
rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
ASSERT_TRUE(rc != -1, "Invalid broadcast address");
to make your client address all slaves within the network, if you have more than one.
You have more info and a short explanation of where this problem is coming from in the libmodbus man page for modbus_set_slave function.
For a very comprehensive example, you can check libmodbus unit tests
And regarding your question number 5, I don't know how to answer it, the zeros you mean are supposed to be the states (true or false) you want to write (or read) to the coils. For writing you can change them with the value field of function modbus_write_bit(ctx, address, value).
I'm very grateful for your reply.
I tested the read/write function using the 'unit-test-server/client' code you recommended.
I've reviewed the code, but there are still many things I don't know.
However, there is an address value that acts after testing each other with unit-test-server/client code and there is an address value that does not work
(Do you know why?).
-Checked and found that the UT_BITS_ADDRESS (address value) value operates from 0x130 to 0x150
-'error Illegal data address' occurs at values below -0x130 and above 0x150
-The address I want to read/write is 0x0001 to 0x0004(Do you know how to do?).
I want to know how to process and transmit data like the TX part of the right picture.
enter image description here
I'm running both client and server in my Linux environment and I'm doing read/write testing.
Among the wrong pictures...[06][FF]... <-- I want to know how to modify FF part (to change the value to 01 as shown in the picture)
enter image description here
and "modbus_set_slave" is the function for modbus rtu?
I'd like to communicate PC Program and Linux device in the end.
so Which part do I use that function?
I thanks for your concern again.
I am trying to perform a simple experiment with an Arduino Uno and the BlueSmirf Bluetooth module from Sparkfun (documentation).
My hardware setup looks like this:
Arduino(power through USB)->BlueSmirf ---(bluetooth)--> PC(no wired connection the the Arduino)->RealTerm
On the Arduino, the following sketch is running:
#include <SoftwareSerial.h>
int txPin = 2;
int rxPin = 3;
SoftwareSerial bluetooth(txPin, rxPin);
void setup() {
bluetooth.begin(115200);
delay(100);
}
void loop() {
String textToSend = "abcdefghijklmnopqrstuvw123456789";
bluetooth.print(textToSend);
delay(5000);
}
Now, the bluetooth connects to the PC just fine, but when I inspect the COM port in RealTerm, I only get the following output:
abdhp1248
Where did the remaining letters and numbers go? It seems like all of the letters that follow the power of two, (i.e. a=1, b=2, d=4, h=8, p=16) print, but none of the rest. Is this just a coincidence?
I think you're running the serial port too fast. As per the comments in the sparkfun BlueSmirf example at https://learn.sparkfun.com/tutorials/using-the-bluesmirf - "115200 can be too fast at times for NewSoftSerial to relay the data reliably".
Reduce the baud rate to 9600 using the code example below, modified from the above web page.
/*
Example Bluetooth Serial Passthrough Sketch
by: Jim Lindblom
SparkFun Electronics
date: February 26, 2013
license: Public domain
This example sketch converts an RN-42 bluetooth module to
communicate at 9600 bps (from 115200), and passes any serial
data between Serial Monitor and bluetooth module.
*/
#include <SoftwareSerial.h>
int bluetoothTx = 2; // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3; // RX-I pin of bluetooth mate, Arduino D3
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup()
{
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
bluetooth.print("$"); // Print three times individually
bluetooth.print("$");
bluetooth.print("$"); // Enter command mode
delay(100); // Short delay, wait for the Mate to send back CMD
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably
bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void loop()
{
String textToSend = "abcdefghijklmnopqrstuvw123456789";
bluetooth.print(textToSend);
delay(5000);
}
I'm using Atmega32 and sim900 for a project. I keep sending "AT" command and wait for the "OK" response, but all I am getting is AT\r\n. I've checked and rechecked wiring and my baud rate, but still getting no where. Whatever I send to sim900 I only get echoed back of the same transmitted string.
Can anyone help me please? I'd really appreciate it.
I'm posting my code here:
int sim900_init(void)
{
while(1)
{
sim_command("AT");
_delay_ms(2000);
}
return 0;
}
void usart_init(void)
{
/************ENABLE USART***************/
UBRRH=(uint8_t)(MYUBRR>>8);
UBRRL=(uint8_t)(MYUBRR); //set baud rate
UCSRB=(1<<TXEN)|(1<<RXEN); //enable receiver and transmitter
UCSRC=(1<<UCSZ0)|(1<<UCSZ1)|(1<<URSEL); // 8bit data format
UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
/***************FLUSH ALL PRIVIOUS ACTIVITIES********************/
flush_usart();
/*********APPOINT POINTERS TO ARRAYS********************/
command=commandArray; // Assigning the pointer to array
response=responseArray; //Assigning the pointer to array
/*****************ENABLE INTRUPT***************************/
sei(); //Enabling intrupts for receving characters
}
void flush_usart(void)
{
response_full=FALSE; //We have not yet received the
}
void transmit_char(unsigned char value)
{
while (!( UCSRA & (1<<UDRE))); // wait while register is free
UDR = value;
}
void sim_command(char *cmd)
{
int j=0;
strcpy(command,cmd);
while(*(cmd+j)!='\0')
{
transmit_char(*(cmd+j));
j++;
}
transmit_char(0x0D); // \r // after all the at commands we should send \r\n so, we send it here after the string
transmit_char(0x0A); // \n
}
unsigned char recieve_char(void)
{
char temp;
while(!(UCSRA) & (1<<RXC)); // wait while data is being received
temp=UDR;
LCDdata(lcdchar,temp);
return temp;
}
void recive_sim900_response(void)
{
static int i=0;
char temp;
temp=recieve_char();
if(temp!='\n' && temp!='\r') // We dont want \r \n that will be send from Sim so we dont store them
*(response+i)=temp;
if(i==8) //when null char is sent means the string is finished- so we have full response
{ //we use them later in WaitForResponse function. we wait until the full response is received
i=0;
response_full=TRUE;
}
else
i++;
}
You were the only one who had exactly the same problem as I.
Somehow the library from gsmlib.org worked but entering AT commands directly using the Arduino serial monitor using the Arduino as a bridge or just an FTDI didn't.
The reason is that apparently the SIM900 expects commands to end with an '\r' character. I found this by trying GTKTerm which worked.
If typing "AT" and pressing enter in GTKTerm what is actually sent is "AT" followed by twice '\r' (0x0d) and one 0x0a
By default GSM module is in echo back ON mode. And you need to change your command.
sim_command("AT");
you need Enter=CR/LF after Command so modify your code like this and give a try
sim_command("AT\r");
And in case you want to turn off echo back of command you send then you should send this command once you have OK response back for AT command.
sim_command("ATE0\r"); //Echo back OFF
sim_command("ATE1\r"); //Echo back ON
I am trying to broadcast data but the output is udp send failed. I chose a random port 33333. What's wrong with my code?
int main()
{
struct sockaddr_in udpaddr = { sin_family : AF_INET };
int xudpsock_fd,sock,len = 0,ret = 0,optVal = 0;
char buffer[255];
char szSocket[64];
memset(buffer,0x00,sizeof(buffer));
memset(&udpaddr,0,sizeof(udpaddr));
udpaddr.sin_addr.s_addr = INADDR_BROADCAST;
udpaddr.sin_port = htons(33333);
xudpsock_fd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
optVal = 1;
ret = setsockopt(xudpsock_fd,SOL_SOCKET,SO_BROADCAST,(char*)&optVal,sizeof(optVal));
strcpy(buffer,"this is a test msg");
len = sizeof(buffer);
ret = sendto(xudpsock_fd,buffer,len,0,(struct sockaddr*)&udpaddr,sizeof(udpaddr));
if (ret == -1)
printf("udp send failed\n");
else
printf("udp send succeed\n");
return (0);
}
One problem is that the address family you are trying to send to is zero (AF_UNSPEC). Although you initialize the family to AF_INET at the top of the function, you later zero it out with memset.
On the system I tested with, the send actually works anyway for some strange reason despite the invalid address family, but you should definitely try fixing that first.
You probably had a problem with your default route (eg, you didn't have one). sendto needs to pick an interface to send the packet on, but the destination address was probably outside the Destination/Genmask for each defined interface (see the 'route' command-line tool).
The default route catches this type of packet and sends it through an interface despite this mismatch.
Setting the destination to 127.255.255.255 will usually cause the packet to be sent through the loopback interface (127.0.0.1), meaning it will be able to be read by applications that (in this case) are run on the local machine.