unity freezes due to use of system.IO.ports.serialport - c#

I am using a c# script to send things over serial. Everything works out fine. The other end is getting all the right data. Problem is, it only works for about 110 to 30 seconds, then unity freezes. I know that this is better suited for the unity forums, but i dont seem to get any replies there, so i have come here.
code below:
using UnityEngine;
using System.Collections;
using System.IO.Ports;
public class NewBehaviourScript : MonoBehaviour {
byte[] StepperAngle = new byte[1];
short servoAngle = 0;
byte[] servoArray = new byte[2];
SerialPort sp = new SerialPort("COM4", 9600);
// Use this for initialization
void Start () {
sp.Open();
sp.ReadTimeout = 1;
}
// Update is called once per frame
void Update () {
StepperAngle[0] = (byte)(transform.localEulerAngles.y * 50/360);
servoAngle = (short)(transform.localEulerAngles.z* 10e8); // turn fl2oat into short. short is split right down center
servoArray[0] = (byte)(servoAngle/10e8);
servoArray[1] = (byte)(servoAngle % 10e8);
sp.Write(StepperAngle,0,1);
//try{
//print(StepperAngle[0]);
//}catch(System.Exception){
//print("stupid " + stepperAngle);
//}
}
}
and also, the culprit IS the line sp.Write(StepperAngle[0]); When commented out everything goes fine.

Yaay. It seems that the issue was not in fact the sp.Write(); call but in fact was the input buffer overflowing. It seems that the arduino code was writing and the unity code was not reading. This caused Unity to freeze up. How removing sp.Write(StepperAngle,0,1); fixed it I have no idea.

Related

Read Pulse value from Coin selector using Rasbperry PI 4 in C# Console Application

Hello guy i have problem in my code it always says low even i already insert coin in Coin Selector
using System;
using System.Device.Gpio;
using System.Threading;
try
{
Thread.Sleep(1000);
int pin = 16;
using var controller = new GpioController();
controller.OpenPin(pin, PinMode.Input);
while (true)
{
String ButtonState = controller.Read(pin).ToString();
Console.WriteLine(ButtonState); //checking the state if the digital value is changing
Thread.Sleep(1000);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Thread.Sleep(10000);
}
This is my current code and I already configure the coin selector.. How can i read the pulse value from the selector?
My wiring is the coin wire is connected to gpio pins (like gpio 16)
I already tried different types of wiring and code but still not working
I believe you are using the wrong pin. GPIO16 = pin36 and pin16 = GPIO23.
https://roboticsbackend.com/raspberry-pi-gpios-default-state/
Here is an picture of the pin layout.
There are multiple libraries that use different layouts so make sure you look at the documentation provided by these libraries.
Good luck!

SharpDX XAudio2: 6 SourceVoice limit

I have been playing around with SharpDX.XAudio2 for a few days now, and while things have been largely positive (the odd software quirk here and there) the following problem has me completely stuck:
I am working in C# .NET using VS2015.
I am trying to play multiple sounds simultaneously.
To do this, I have made:
- Test.cs: Contains main method
- cSoundEngine.cs: Holds XAudio2, MasteringVoice, and sound management methods.
- VoiceChannel.cs: Holds a SourceVoice, and in future any sfx/ related data.
cSoundEngine:
List<VoiceChannel> sourceVoices;
XAudio2 engine;
MasteringVoice master;
public cSoundEngine()
{
engine = new XAudio2();
master = new MasteringVoice(engine);
sourceVoices = new List<VoiceChannel>();
}
public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
{
/**
* Set up and start SourceVoice
*/
NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
SoundStream soundStream = new SoundStream(fileStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source);
sourceVoices.Add(voice);
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
return voice;
}
Test.cs:
cSoundEngine engine = new cSoundEngine();
total = 6;
for (int i = 0; i < total; i++)
{
string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + #"\Assets\Planet.wav";
VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
}
Console.Read(); //Input anything to end play.
There is currently nothing worth showing in VoiceChannel.cs - it holds 'SourceVoice source' which is the one parameter sent in the constructor!
Everything is fine and well running with up to 5 sounds (total = 5). All you hear is the blissful drone of Planet.wav. Any higher than 5 however causes the console to freeze for ~5 seconds, then close (likely a c++ error which debugger can't handle). Sadly no error message for us to look at or anything.
From testing:
- Will not crash as long as you do not have more than 5 running sourcevoices.
- Changing sample rate does not seem to help.
- Setting inputChannels for master object to a different number makes no difference.
- MasteringVoice seems to say the max number of inputvoices is 64.
- Making each sfx play from a different wav file makes no difference.
- Setting the volume for sourcevoices and/or master makes no difference.
From the XAudio2 API Documentation I found this quote: 'XAudio2 removes the 6-channel limit on multichannel sounds, and supports multichannel audio on any multichannel-capable audio card. The card does not need to be hardware-accelerated.'. This is the closest I have come to finding something that mentions this problem.
I am not well experienced with programming sfx and a lot of this is very new to me, so feel free to call me an idiot where appropriate but please try and explain things in layman terms.
Please, if you have any ideas or answers they would be greatly appreciated!
-Josh
As Chuck has suggested, I have created a databank which holds the .wav data, and I just reference the single data store with each buffer. This has improved the sound limit up to 20 - however this has not fixed the problem as a whole, likely because I have not implemented this properly.
Implementation:
class SoundDataBank
{
/**
* Holds a single byte array for each sound
*/
Dictionary<eSFX, Byte[]> bank;
string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
public SoundDataBank()
{
bank = new Dictionary<eSFX, byte[]>();
bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + #"\Assets\Planet.wav"));
bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav"));
}
public Byte[] GetSoundData(eSFX sfx)
{
byte[] output = bank[sfx];
return output;
}
}
In SoundEngine we create a SoundBank object (initialised in SoundEngine constructor):
SoundDataBank soundBank;
public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
{
/**
* sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
*/
byte[] buffer = soundBank.GetSoundData(sfx);
MemoryStream memoryStream = new MemoryStream(buffer);
SoundStream soundStream = new SoundStream(memoryStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
sourceVoices.Add(voice);
return voice;
}
Following this implementation now lets me play up to 20 sound effects - but NOT because we are playing from the soundbank. Infact, even running the old method for sound effects now gets up to 20 sfx instances.
This has improved up to 20 because we have done NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav") in the constructor for the SoundBank.
I suspect NativeFile is holding a store of loaded file data, so you regardless of whether you run the original SoundEngine.AddAndPlaySFX() or SoundEngine.AddAndPlaySFXFromStore(), they are both running from memory?
Either way, this has quadrupled the limit from before, so this has been incredibly useful - but requires further work.

i2c read data from sensor with Netduino

I start learning Netduino short time ago. At now, I want to use it with MS5803 30BAR sensor. This Components communicate with I2C Protocol. I learned this protocol a little bit but not enough.
I wrote introducing of code. When I came main code, I did not do anything. My code is below.
Can anybody help about this matter? I will be so pleased :)
public class Program
{
public static void Main()
{
// Configuration of MS5803 30BA
I2CDevice i2c = new I2CDevice(new I2CDevice.Configuration(0x76>>1, 400));
byte[] read = new byte[1];
I2CDevice.I2CTransaction[] i2cTx = new I2CDevice.I2CTransaction[1];
i2cTx[0] = I2CDevice.CreateReadTransaction(read);
// ???
}
}
It looks like you're missing the I2C.Execute call. Without knowing anything about the device you're communicating with this will at least start the transmission.
Try to add this line after you create the read transaction.
i2c.Execute(i2cTX[0],500);
byte[] returnByte = new byte[3];
var readX = new I2CDevice.I2CTransaction[] {I2CDevice.CreateReadTransaction(returnByte) };
int executed = 0;
I2CDevice i2c = new I2CDevice(new I2CDevice.Configuration(0x76, 400));
executed = i2c.Execute(readX, 400);
if (executed == 0)
{
//Debug.Print("Read FAIL!");
}
else
{
//Debug.Print("Read SUCCESS!");
}
//throw new Exception("I2C transaction failed");
//you will need to do some bit shifting with the readX array to get your values.
}
Here an excellent document on netMF i2c: https://www.ghielectronics.com/docs/12/i2c
The device data sheet:
http://www.amsys-sensor.eu/sheets/amsys.en.ms5803_30ba.pdf

Read data from serial port device in c#

We need to weigh a bunch of products, and store their weight in a DB.
We have a scale that can be plugged through a serial port, and then we want to scan the product's barcode with a barcode scanner.
I need to write a program that will read the scale data. I have read and followed a bunch of articles on how to do it, but I can't seem to make it work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Weighting
{
public partial class Form1 : Form
{
SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
public Form1()
{
this.InitializeComponent();
this.port.Open();
this.port.Encoding = Encoding.ASCII;
this.port.Handshake = Handshake.None;
this.port.RtsEnable = true;
this.port.ReceivedBytesThreshold = 1;
this.port.DataReceived += new SerialDataReceivedEventHandler(this.port_DataReceived);
}
~Form1()
{
this.port.Close();
this.port.Dispose();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
char[] data = new char[] { 's', ' ', '\r', '\n' };
this.port.Write(data, 0, 1);
Thread.Sleep(500);
var InputData = this.port.ReadLine();
if (!string.IsNullOrEmpty(InputData))
{
MessageBox.Show(InputData);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var InputData = this.port.ReadLine();
this.BeginInvoke(new Action(() =>
{
MessageBox.Show(InputData);
}));
}
}
}
The DataReceived handler is never fired, and ReadLine() never returns anything.
The specs of the scale can be found here (chapter 10) : http://www.kern-sohn.com/manuals/files/English/FCB-BA-e-0911.pdf
Note that it's very possible that my serial port, or my cable don't work, or that the scale doesn't send data, or whatever (it's been about 15 years since I have used a serial port device). How can y test that everything works ?
Thank you!
Update
The connection parameters have been taken (and interpreted) from an old Excel macro:
With MSComm1
.CommPort = 1
.Handshaking = 0
.RThreshold = 1
.RTSEnable = True
.Settings = "9600,n,8,1"
.SThreshold = 1
.PortOpen = True
End With
This macro supposedly used to work a few years back, but I couldn't make it work myself (the MSComm1 object is not defined).
Your connection setup looks to match the documentation, but your code smells quite a bit (this is nothing against you, the .NET SerialPort is a nightmare to work with!).
You are not setting the SerialPort.NewLine property to Environment.NewLine (CRLF) and it is instead using the default value of \n (LF). This alone doesn't solve the problem, because you would just have a carriage return at end of the result of calling ReadLine().
The real issue is the DataReceived handler. A lot of people recommend using it but through my exhaustive testing it diminishes determinism of results greatly, particularly when communicating in a friendly encoding such as ASCII. Because you initiate the command by sending your s character, I would honestly get rid of it, and just call ReadLine() right after your Write. (You do not need to Thread.Sleep because ReadLine will simply block until the terminated string is read in or a timeout is reached).
Your ReceivedBytesThreshold is set to 1, and that specifies the buffer size to fill before raising DataReceived so you're trying to read a whole line for every byte received (give or take, DataReceived is very unpredictable).
Here's an example of how I would clean it up (in addition to removing the DataReceived handler). I can't be certain if this will clear your problem up, but making these corrections will lead to much easier debugging. As a temporary change to aid with debugging, you could bring your Sleep call back in and call ReadExisting instead of ReadLine and examine what it pulls (if anything) from the buffer.
private void button2_Click(object sender, EventArgs e)
{
try
{
this.port.Write("s");
var InputData = this.port.ReadLine();
if (!string.IsNullOrEmpty(InputData))
{
MessageBox.Show(InputData);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I've just finished writing a library to sit on top of the .NET SerialPort for my company and have run into the same sort of issues (plus a million more) as you. If you would like further clarification feel free to ask.
As pointed out by #user3894601, the problem was solved by using the original cable, and using a USB adapter.

MonoDroid Bluetooth

I have been working with Monodroid for a few days and still can't figure out how to send a command through Bluetooth.
This is my scenario: I have a Tablet/Cellphone working with Android 2.1+ and need to send and receive data to a Bluetooth printer (in bytes).
What i managed so far:
using Android.Bluetooth; // library necessary
BluetoothAdapter bth = BluetoothAdapter.DefaultAdapter;
if (!bth.IsEnabled)
bth.Enable();
ICollection<BluetoothDevice> bthD = bth.BondedDevices;
foreach (BluetoothDevice d in bthD)
{
if (d.Name == "DPP-350")
{
Java.Util.UUID UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
// Get the BLuetoothDevice object
BluetoothSocket s = d.CreateRfcommSocketToServiceRecord(UUID);
s.Connect();
// Try to send command
...
s.Close()
}
}
The program asks for the pairing info, with is done correctly.
I have tried many ways to send the command:
// the command
// Self_Test = Chr(27) + Chr(84) = ESC T
byte[] dBytes = System.Text.Encoding.GetEncoding(1252).GetBytes(Self_Test);
// wont work
new Java.IO.ObjectOutputStream(s.OutputStream).Write(dBytes);
// wont work
System.IO.Stream st = s.OutputStream;
if (st.CanWrite)
{
st.Write(dBytes, 0, dBytes.Length);
st.Flush();
}
// wonk work
s.OutputStream.Write(dBytes, 0, dBytes.Length);
s.OutputStream.Flush();
No error is raised. I'm running out of options here...
Thanks in advance!
I know this is a very old thread, but I wanted to post a reply so others will know the answer. I too searched hard with no luck.
s.OutputStream.BeginWrite(buffer, 0, buffer.Length,new AsyncCallback(delegate {}), State.Connected);
Thanks.

Categories

Resources