Sending numbers via Serialport from C# to Java - java

I'm making a Bluetooth quadcoopter using Arduino. I have no problem sending letters, but I cant seem to write or read numbers.
I'm not very good at programing so bear with me.
C# code:
private void button1_Click(object sender, EventArgs e)
{
int testInt = 35;
byte[] testByte = BitConverter.GetBytes(testInt);
serialPort1.Write(testByte, 0, 0);
int i = BitConverter.ToInt32(testByte,0);
label5.Text = i.ToString();
}
Here I've tried to convert to send a byte, at first I just sent it directly as a string. I get the same result from both ways.
Arduino code:
<code>void loop()
{
// put your main code here, to run repeatedly:
if(Serial.available())
{
int data = Serial.read();
if(data=='35')
{
digitalWrite(13, HIGH);
}
}
}
Why don't the LEDs light up? How do I read numbers from a serial port?

This sends a single byte (0 to 255):
private void button1_Click(object sender, EventArgs e) {
// set up to send only one byte
byte[] testByte = {35};
// send one byte
serialPort1.Write(testByte, 0, 1);
}
And this receives and interprets it on the Arduino:
void loop() {
if (Serial.available()) {
byte data = Serial.read();
if (data == 35) {
digitalWrite(13, HIGH);
}
}
}
If you think you might send a number greater than 255, it's probably just as easy to send a string. Add a new line character to the end of the string:
String testString = "35\n";
and use the new line to let the Arduino know you're done sending the code, something like this:
#define MAX_SIZE 5;
char button[MAX_SIZE+1];
if (Serial.available()) {
int bytesRead = Serial.readBytesUntil ('\n', button, MAX_SIZE);
if (bytesRead > 0) {
button[bytesRead] = '\0';
int result = atoi(button);
if (result == 35) {
digitalWrite(13, HIGH);
} else {
digitalWrite(13, LOW);
}
}
}

Related

Arduino Servo working in setup function but not with bluetooth command

i am experiencing a very strange issue, i wrote code for arduino UNO 3 which is designed to unlock door using servo motor, components attached are following
Servo Motor
1 Red Led (for failure alert)
1 Green Led (for success alert)
1 Buzzer (for audible alert on unlock)
The code is following
#include <Arduino_JSON.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>
#include <Servo.h>
String com = "";
const int buzzer = 6;
const int ledfalse = 8;
const int ledtrue = 13;
const int servo = 11;
Servo myservo;
SoftwareSerial mySerial(2, 3);
void ResetAdmin()
{
for (int i = 0 ; i < EEPROM.length() ; i++)
EEPROM.write(i, 0);
Blink(ledtrue, 2);
}
void WriteAdmin(String admin)
{
byte len = admin.length();
EEPROM.write(0, len);
for (int i = 0; i < len; i++)
{
EEPROM.write(i + 1, admin[i]);
}
Blink(ledtrue, 2);
}
String ReadAdmin()
{
int newStrLen = EEPROM.read(0);
char data[newStrLen + 1];
for (int i = 0; i < newStrLen; i++)
{
data[i] = EEPROM.read(i + 1);
}
data[newStrLen] = '\0';
return String(data);
}
void Unlock()
{
Alert();
myservo.write(0);
delay(500);
myservo.write(90);
delay(6500);
myservo.write(360);
delay(500);
myservo.write(90);
}
void Blink(int type, int times)
{
for(int i = 1; i <= times; i++)
{
digitalWrite(type, HIGH);
delay(80);
digitalWrite(type, LOW);
delay(80);
}
}
void Alert()
{
for(int i = 1; i <= 4; i++)
{
tone(buzzer, 1000);
delay(80);
noTone(buzzer);
delay(80);
}
}
void ProcessCommand(String command)
{
if(command == "unlock")
Unlock(); //not works here
else if(command == "reset")
ResetAdmin();
else
{
Blink(ledfalse, 2);
}
}
void setup()
{
myservo.attach(servo);
mySerial.begin(9600);
pinMode(buzzer, OUTPUT);
pinMode(ledfalse, OUTPUT);
pinMode(ledtrue, OUTPUT);
//Unlock() or Blink(ledtrue, 4) or Alert() works here
digitalWrite(ledtrue, HIGH);
digitalWrite(ledfalse, HIGH);
delay(3000);
digitalWrite(ledtrue, LOW);
digitalWrite(ledfalse, LOW);
}
void loop()
{
while(mySerial.available() > 0)
{
delay(10);
com += (char)Serial.read();
}
if(com.length() > 0)
{
JSONVar doc = JSON.parse(com);
if (JSON.typeof(doc) != "undefined")
{
String admin = ReadAdmin();
if(admin == "")
{
admin = doc["admin"];
WriteAdmin(admin);
}
if(admin == doc["admin"])
{
ProcessCommand((const char*) doc["command"]);
}
else
{
Blink(ledfalse, 2);
}
}
else
{
Blink(ledfalse, 2);
}
com = "";
}
delay(10);
}
The java snippet for sending command is following
private void Unlock() {
if (btSocket != null) {
try {
String payload = "{\"admin\": \"" + getUUID() + "\", \"command\": \"unlock\"}";
btSocket.getOutputStream().write(payload.getBytes());
} catch (Exception e) {
e.printStackTrace();
biometricLoginButton.setImageResource(R.drawable.warning);
failed = true;
Toast.makeText(getBaseContext(), "Error occurred while unlocking", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getBaseContext(), "Door Lock not connected", Toast.LENGTH_SHORT).show();
biometricLoginButton.setImageResource(R.drawable.warning);
failed = true;
}
}
The issue is when i put the Alert(), Unlock() & Blink() function in the Arduino setup function then alert is working fine and so do the other two, but when the same functions called using Bluetooth signal none of them works. Note that the function is called as servo try to move but not correctly, this shows that Bluetooth is receiving data correctly from android and conditions are being evaluated correctly.
Finally i myself figured out the issue, basically the problem was with the EEPROM of the Arduino the problematic section of the code is following
String admin = ReadAdmin();
if(admin == "")
{
//on first run it never returned empty string, may be my reading function bug
admin = doc["admin"];
WriteAdmin(admin);
}
if(admin == doc["admin"])
{
//due to garbage value compared with actual one this block never executed
rocessCommand((const char*) doc["command"]);
}
else
{
Blink(ledfalse, 2);
}
First condition is for the first run so that when there is no admin stored in the EEPROM, then store the one coming in the JSON, but i don't know why but it was always some garbage value instead of empty or null string that's why the admin was not being matched e.g. the garbage value and the one received in JSON and thus not running the Unlock sequence

Netty client receives the message delay

1.scene description:
Device sen data to Netty Server(about ## 20ms intervals ##), Netty Server forward msg to Client ## Immediately ##(IOS or Android).
2.Associated business code
ctx.writeAndFlush(msg)
protected void doWrite(ChannelOutboundBuffer in) throws Exception {
int writeSpinCount = -1;
boolean setOpWrite = false;
for (;;) {
//Get the data of the first node that needs to be flushed
Object msg = in.current();
if (msg instanceof ByteBuf) {
ByteBuf buf = (ByteBuf) msg;
boolean done = false;
long flushedAmount = 0;
// Get the number of spin lock iterations
if (writeSpinCount == -1) {
writeSpinCount = config().getWriteSpinCount();
}
// Spin, write out the current node
for (int i = writeSpinCount - 1; i >= 0; i --) {
int localFlushedAmount = doWriteBytes(buf);
if (localFlushedAmount == 0) {
setOpWrite = true;
break;
}
flushedAmount += localFlushedAmount;
if (!buf.isReadable()) {
done = true;
break;
}
}
in.progress(flushedAmount);
// After writing, delete the current node
if (done) {
in.remove();
} else {
break;
}
}
}
}
protected int doWriteBytes(ByteBuf buf) throws Exception {
final int expectedWrittenBytes = buf.readableBytes();
return buf.readBytes(javaChannel(), expectedWrittenBytes);
}
3.issue
The netty Server can receive the device data in time
and netty Server can write the data to Socket Buffer in time also.
But The Netty client receives the message delay!!!(eg. 5s delay)
4.Server bandwidth configuration
Inbound 100M/bps bit per seconds.
Outbound 5M/bps bit per seconds.
Client terminal length packer caused by the problem.

Check if an IP is contained in a set of ranges?

Does anyone know of a clean way to check if an IP is contained in a set of ranges?
I'm getting a response that looks like this:
"ipRange": "10.12.0.0/16,10.80.0.0/15,10.83.0.0/16,10.101.0.0-10.103.255.255,10.108.0.0/16,10.121.0.0/16,10.123.0.0/16,10.127.0.0/16,10.129.0.0/16,10.131.0.0/16,10.133.0.0/16,10.135.0.0-10.139.255.255,10.208.0.0/14,10.215.0.0/16,10.218.0.0/15,10.233.0.0/16,172.17.128.0-172.19.255.255,172.24.0.0/15,192.168.0.0/16"
And I need to see if an IP is in any of those works. The ones with "slash" notation should be straight forward, but what about the ranges where they have "-"?
An IPv4 address is nothing else than a unsigned int32. The easy way to check whether IP address A with network mask X is in subnet B with network mask Y:
convert A to uint32
convert B to uint32
convert Y to uint32
if (A & Y) == (B & Y) then yes
I've commented the code below. Basically, I split the "ipRanges" into distinct ipAddresses or ipAddressRanges by looking for ",". Then test the given ip to each of those to see if it is good.
String ipRange = "10.12.0.0/16,10.80.0.0/15,10.83.0.0/16,10.101.0.0-10.103.255.255,10.108.0.0/16,10.121.0.0/16,10.123.0.0/16,10.127.0.0/16,10.129.0.0/16,10.131.0.0/16,10.133.0.0/16,10.135.0.0-10.139.255.255,10.208.0.0/14,10.215.0.0/16,10.218.0.0/15,10.233.0.0/16,172.17.128.0-172.19.255.255,172.24.0.0/15,192.168.0.0/16";
public IPAddressTest() {
String ipToTest = "10.101.0.0";
System.out.println(String.format("[%s] is in range (%b)", ipToTest, isInRange(ipToTest)));
}
private Boolean isInRange(String ipToTest) {
String[] ranges = ipRange.split(",");
for (String _range : ranges) {
String range = _range.indexOf("/") > -1 ? _range.substring(0, _range.indexOf("/")) : _range; // cut off the /xx if it exists
boolean test = test(ipToTest, range);
if (test) {
return true;
}
}
return false;
}
private Boolean test(String ipToTest, String ipRange) {
String[] ranges = ipRange.split("-"); // Do we have a range or just a single ip
String loRange = ranges[0]; // grab the first
String hiRange = ranges.length > 1 ? ranges[1] : null; // If there a range grab the top end, else nothing
if (hiRange == null) { // if a single ip, just do a string compare
return ipToTest.equals(loRange);
} else { // if a range then make sure each part is between the min and max
String[] partsToTest = ipToTest.split("\\."); // get each part of the ip
String[] partsLoRange = loRange.split("\\."); // get each part of the ip
String[] partsHiRange = hiRange.split("\\."); // get each part of the ip
int test = 0; // this will be our litmus test. if it = 15 when we are done, then each part is good, 63 of ipv6
for (int i = 0; i < 4; i++) { // change 4 to 6 for ipv6
int value = Integer.parseInt(partsToTest[i]); //get the int
int lo = Integer.parseInt(partsLoRange[i]); //get the int
int hi = Integer.parseInt(partsHiRange[i]); //get the int
if (value >= lo && value <= hi) { // if we have a good value, set the bit on 'test'
test += Math.pow(2, i);
}
}
if (test == 15) {
return true;
}
}
return false;
}
public static void main(String[] args) {
new IPAddressTest();
}

bulkTransfer returns positive value but communication is not successful

As stated by Google at Android Developers
public int bulkTransfer (UsbEndpoint endpoint, byte[] buffer, int
length, int timeout)
Returns length of data transferred (or zero) for success, or negative value for failure
Well, after performing a bulkTransfer in my app for a USB CDC communication
// send data to usb device
byte[] bytes = data.getBytes();
sentBytes = connection.bulkTransfer(output, bytes, bytes.length, 1000);
sentBytes is receiving the value of 16, which is great, because I'm sending 16 bytes indeed.
It should indicate that the bytes were sent correctly. :-)
However, they're NOT. I can't see any results on the other side.
After doing a rearch I found out that it could be an Interface problem, so here it's how I'm getting it from the device:
private void setupConnection()
{
// find the right interface
for(int i = 0; i < usbDevice.getInterfaceCount(); i++)
{
// communications device class (CDC) type device
if(usbDevice.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
{
intf = usbDevice.getInterface(i);
// find the endpoints
for(int j = 0; j < intf.getEndpointCount(); j++)
{
if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
{
// from android to device
output = intf.getEndpoint(j);
}
if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
{
// from device to android
input = intf.getEndpoint(j);
}
}
}
}
}
What could I be possibly missing?

Raspberry PI + Wiegand RFID

I have problem with my Wiegand RFID reader (26bit). I have write simple Java app and everything seems fine. But after 10 reads for example, it starts to shift bits. Is RPi Raspbian to slow for Wiegand time protocol?
Here is sample code and output
package classes;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.RaspiPin;
public class Test {
public static char[] s = new char[10000];
static int bits = 0;
public static void main(String[] args) {
// create gpio controller
final GpioController gpio = GpioFactory.getInstance();
// provision gpio pin #02 as an input pin with its internal pull down
// resistor enabled
final GpioPinDigitalInput pin0 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_UP);
final GpioPinDigitalInput pin1 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_UP);
System.out.println("PINs ready");
Thread th = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
if (pin0.isLow()) { // D1 on ground?
s[bits++] = '0';
while (pin0.isLow()) {
}
}
if (pin1.isLow()) { // D1 on ground?
s[bits++] = '1';
while (pin1.isLow()) {
}
}
if (bits == 26) {
bits=0;
Print();
}
}
}
});
th.setPriority(Thread.MAX_PRIORITY);
th.start();
System.out.println("Thread start");
for (;;) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected static void Print() {
for (int i = 0; i < 26; i++) {
System.out.write(s[i]);
}
System.out.println();
bits = 0;
}
}
and output:
10100100111111110110011011
10100100111111110110011011
10100100111111110110011011
10100100111111110110011011
10100100111111110001101110
10010011111111011001101110
10010011111111011001101110
10010011111111011001101110
10010011111111011001101110
10010011111111011001101110
10010011111111011001101110
Your printf statements may be causing the problem. Try storing the data and printing it at the end. printf tends to be slow (it involves several context switches).
Also, it seems you have no way of detecting if you miss a bit. I would say try a timeout, so if you don't get 26 bits in time reset your counter. That way you're not looping around reading nothing, and eventually getting misaligned data.
I have done this in C and python on a pi and also on an arduino. From my experience as #woodrow douglas says you need to capture the bits in a loop or use interrupts (better) and use a timeout which you increase each time you receive a bit and then print it out once you are sure you have all the bits (timed out).
This is how I do this on arduino using interrupts.
void zero(){
bit_count ++;
bit_holder = (bit_holder << 1) + 0; //shift left one and add a 0
timeout = t;
}
void one(){
bit_count ++;
bit_holder = (bit_holder << 1) + 1; //shift left one and add a 1
timeout = t;
}
void loop() {
timeout --;
if (timeout == 0 && bit_count > 0){
lcd.clear();
lcd.print("Dec:");
lcd.print(bit_holder);
lcd.setCursor(0,1);
lcd.print("Hex:");
lcd.print(String(bit_holder,HEX));
Serial.print("bit count= ");
Serial.println(bit_count);
Serial.print("bits= ");
Serial.println(bit_holder,BIN);
oldbit = bit_holder; //store previous this value as previous
bit_count = 0; //reset bit count
bit_holder = 0; //reset badge number
}
}
I never got any issues using C on Pi but I did get issues using python as it is not as real time. The only way it would work in Python was by using interrupts and I managed too get the bad read rate down to something like 1 in 200 but never completely remove it.
What I did in the end was use some C to collect the bits then call my python script with the bits for processing.
If you are interested this is the C code I use:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
int r1data0 = 6; //pin 22
int r1data1 = 7; // Pin 7
// green goes to same as relay
int r1beep = 0; //pin 11
int r2data0 = 10; /* P1-24 */
int r2data1 = 11; /* P1-26 */
//green goes to same as relay
int r2beep = 0;
int i1 = 0;
int i2 = 0;
//generic variables
int t = 5;
int blank; //blank variable to reset bits
int rel1time = 0;
int rel2time = 0;
int rel1 = 5;
int previoust;
//reader 1variables
int r1bits; // Collected bits storage area
int r1bit_count = 0; //to measure the size of bits
int oldr1bit_count = 0; //somewhere to store bitcount to send to python
int r1timeout; //timout to return correct value
char r1command[40];
int r1ret;
//reader 2 variables
int r2bits; // Collected bits storage area
int r2bit_count = 0; //to measure the size of bits
int oldr2bit_count = 0;
int r2timeout; //timout to return correct value
char r2command[40];
pthread_t threads;
void access_denied(int red){
int pin;
if(red = 1){pin = r1beep;}
if(red = 2){pin = r2beep;}
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
delay(300);;
digitalWrite(pin, HIGH);
delay(200);
digitalWrite(pin, LOW);
delay(300);
digitalWrite(pin, HIGH);
delay(200);
digitalWrite(pin, LOW);
delay(300);
digitalWrite(pin, HIGH);
}
void *r1python_thread(void *val){
sprintf(r1command,"python access.py r1 %X %X", oldr1bit_count, val); //build python command
FILE* file = popen(r1command, "r"); //execute command using popen
char buffer[5];
fscanf(file, "%100s", buffer); //read command output
pclose(file);
//printf("buffer is : %s\n", buffer);
rel1time = atoi(buffer); //convert returned string to int
if(rel1time == 0){access_denied(1);}
pthread_exit(NULL);
}
void *r2python_thread(void *val){
sprintf(r2command,"python access.py r2 %X",val); //build python command
FILE* file = popen(r2command, "r"); //execute command using popen
char buffer[5];
fscanf(file, "%100s", buffer); //read command output
pclose(file);
//printf("buffer is : %s\n", buffer);
rel2time = atoi(buffer); //convert returned string to int
pthread_exit(NULL);
}
//reader 1 bit functions
void onebit0(){ //adds a 0
r1bit_count ++; //increase bit count
r1bits = (r1bits << 1) + 0;
r1timeout = t; //reset timeout
}
void onebit1(){ //adds a 1
r1bit_count ++;
r1bits = (r1bits << 1) + 1;
r1timeout = t;
}
//reader 2 bit functions
void twobit0(){ //adds a 0
r2bit_count ++; //increase bit count
r2bits = (r2bits << 1) + 0;
r2timeout = t; //reset timeout
}
void twobit1(){ //adds a 1
r2bit_count ++;
r2bits = (r2bits << 1) + 1;
r2timeout = t;
}
int main(){
wiringPiSetup(); //initialise wiringPi
pinMode (r1data0, INPUT); // set reader 1 data0 as input
pinMode (r1data1, INPUT); // set reader 1 data1 as input
pinMode (r2data0, INPUT); // set reader 2 data0 as input
pinMode (r2data1, INPUT); // set reader 2 data1 as input
//reader 1
wiringPiISR(r1data0, INT_EDGE_FALLING, onebit0); // set interrupt on data 0 if it falls call bit0 function
wiringPiISR(r1data1, INT_EDGE_FALLING, onebit1); // set interrupt on data 1 if it falls call bit1 function
//reader 2
wiringPiISR(r2data0, INT_EDGE_FALLING, twobit0); // set interrupt on data 0 if it falls call bit0 function
wiringPiISR(r2data1, INT_EDGE_FALLING, twobit1); // set interrupt on data 1 if it falls call bit1 function
while (1){ //loop
if (r1bit_count > 0 ){ //if bits is not empty
r1timeout--; // reduce timeout by 1
if(r1timeout == 0){ //and it has timed out ie no more bits coming
//printf("%X\n",r1bits);
pthread_create(&threads, NULL, r1python_thread,(void *) r1bits); //start new thread for python program
oldr1bit_count = r1bit_count;
r1bit_count = 0; //reset bit count
r1bits = blank; //clear bits cariable
r1timeout = t; //reset timeout
}
}
if (r2bit_count > 0 ){ //if bits is not empty
r2timeout--; // reduce timeout by 1
if(r2timeout == 0){ //and it has timed out ie no more bits coming
pthread_create(&threads, NULL, r2python_thread,(void *) r2bits); //start new thread for python program
r2bit_count = 0; //reset bit count
r2bits = blank; //clear bits cariable
r2timeout = t; //reset timeout
}
}
if (rel1time > 0){
pinMode(rel1, OUTPUT);
int diff = time(NULL) - previoust;
if(diff >= 1){
previoust = time(NULL);
rel1time--;
}
}
else{
pinMode(rel1, INPUT);
previoust = time(NULL);
}
delay(1);
}
return 0;
}

Categories

Resources