Raspberry 3 push button in c# - c#

I'm trying out C# for Raspberry through Visual Studio and windows 10 IoT. Just took me an eternity to make everything work, but I slowly got there. I got my leds workings following their outdated 2 years old tutorials. I'm now trying to add a button to my breadboard to turn the leds on and off... Sadly, This doesn't work at all. It's like ValueChanged is never triggered.
I followed this guide: https://developer.microsoft.com/en-us/windows/iot/samples/pushbutton
My button is wired like: 1 pin directly to ground and the other one to GPIO18 (Pin 12)
Before thequestion comes, yes I did try using GPIO5 too. I just went back to GPIO18 as it was working on my python script before.
This is the code I'm trying to run, but having button problems (leds are fine):
public sealed class StartupTask : IBackgroundTask
{
private GpioController gpio = GpioController.GetDefault();
private GpioPin pinRed;
private GpioPin pinBlue;
private GpioPin pinButton;
private GpioPinValue pinValue;
private const int BLUE_PIN = 19;
private const int RED_PIN = 26;
private const int BUTTON_PIN = 18;
public void Run(IBackgroundTaskInstance taskInstance)
{
Debug.WriteLine("initialising");
InitGpio();
if (pinRed != null)
{
pinValue = GpioPinValue.High;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
}
private void InitGpio()
{
gpio = GpioController.GetDefault();
if (gpio == null)
{
pinRed = null;
pinBlue = null;
pinButton = null;
Debug.WriteLine("Failed starting GPIO");
return;
}
pinValue = GpioPinValue.Low;
pinRed = gpio.OpenPin(RED_PIN);
pinRed.Write(pinValue);
pinRed.SetDriveMode(GpioPinDriveMode.Output);
pinBlue = gpio.OpenPin(BLUE_PIN);
pinBlue.Write(pinValue);
pinBlue.SetDriveMode(GpioPinDriveMode.Output);
pinButton = gpio.OpenPin(BUTTON_PIN);
if (pinButton.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
{
Debug.WriteLine("Is supported");
pinButton.SetDriveMode(GpioPinDriveMode.InputPullUp);
}
else
{
Debug.WriteLine("Not supported");
pinButton.SetDriveMode(GpioPinDriveMode.Input);
}
pinButton.DebounceTimeout = TimeSpan.FromMilliseconds(50);
pinButton.ValueChanged += buttonValueChange;
Debug.WriteLine("GPIO initialised");
}
private void buttonValueChange(GpioPin sender, GpioPinValueChangedEventArgs e)
{
Debug.WriteLine("here");
if (e.Edge == GpioPinEdge.FallingEdge)
{
Debug.WriteLine("Button push");
pinValue = (pinValue == GpioPinValue.Low) ? GpioPinValue.High : GpioPinValue.Low;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
else
{
Debug.WriteLine("Button release");
}
}
}
Yes, lots of debug lines, as I said, trying out C# on Raspberry (InputPullUp is supported). The "here" in buttonValueChange is never triggered. I did the exact same wiring setup on Python and it worked flawlessly on the same pins.

It is suggested here ValueChanged not firing with C# Win10 Iot that "When the Run method ends, unless a deferral object is created, the Background Application ends."
As such you could try to add this line to your Run code:
var deferral = taskInstance.GetDeferral();
And see if it helps.

Related

C# GeoLocation Watcher taking too long to get coordinates

I have created a Windows Form App for our works Windows Tablets (windows 10) to track location.
The class I have created is below:
class LocationServices
{
private GeoCoordinateWatcher myWatcher;
private bool fgWatcherStarted = false;
public LocationServices()
{
myWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
public LatLon GetDeviceLocation()
{
LatLon myReturn = new LatLon();
System.Device.Location.GeoCoordinate myPosition = new System.Device.Location.GeoCoordinate();
try
{
if (!fgWatcherStarted)
{
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
myPosition = myWatcher.Position.Location;
if (myPosition.IsUnknown)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = "Unknown Position";
}
else
{
myReturn.Latitude = myPosition.Latitude;
myReturn.Longitude = myPosition.Longitude;
myReturn.strMessage = myPosition.Course.ToString();
}
}
catch (Exception ex)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = ex.Message.ToString();
}
return myReturn;
}
}
In my code I am running through every few seconds and getting the location by calling the class above.
If I am connected to wifi (running from my desk) it gets the location instantly and works as expected, but from the device it returns 0 for a significant amount of time and then suddenly starts working and works perfectly fine with no issues.
Is there anything I can do to make this start quicker? I initially thought it could be the location/signal but I have tried loading in the same place and leaving it and once it initialises it works perfectly but it's the initial coordinates that take ages to load.
Looks as though there needs to be a position change for it to return a value, see the answer here: https://stackoverflow.com/a/52910209/6639187
Not quite sure about your way of getting the coordinates, I used to do the following method - hope this helps (run it in a console app and check as follows)
class Program
{
private static GeoCoordinateWatcher Watcher;
static void Main(string[] args)
{
Watcher = new GeoCoordinateWatcher();
Watcher.StatusChanged += Watcher_StatusChanged;
Watcher.Start();
Console.ReadLine();
}
static void Watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
if (e.Status == GeoPositionStatus.Ready)
{
if (Watcher.Position.Location.IsUnknown)
{
Console.Write("Cannot find location");
}
else
{
Console.WriteLine("Lat: " + Watcher.Position.Location.Latitude.ToString());
Console.WriteLine("Lon: " + Watcher.Position.Location.Longitude.ToString());
}
}
}
}

Continuously getting data from heart rate monitor

I've been working on a project that reads a person's heart rate from a Polar H7 hrm. I've been successful in connecting the device and getting the heart rate which the program shows as text in the UI. However, there are instances where the program suddenly stops getting input from the device.
I have already checked the connection of the device to my Win 10 laptop and saw that it was stable, there were also no exceptions getting thrown by the program. The text simply stops changing.
Here is the code I've written:
public sealed partial class MainPage : Page
{
private GattDeviceService device;
public MainPage()
{
this.InitializeComponent();
init();
}
async void init()
{
var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate));
Status.Text = devices.Count.ToString();
device = await GattDeviceService.FromIdAsync(devices[0].Id);
enableSensor();
}
private async void enableSensor()
{
IReadOnlyList<GattCharacteristic> characteristicList;
characteristicList = device.GetAllCharacteristics();
if (characteristicList != null)
{
GattCharacteristic characteristic = characteristicList[0];
if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += SendNotif;
await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
}
}
async void SendNotif(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
if (eventArgs.CharacteristicValue.Length != 0) {
byte[] hrData = new byte[eventArgs.CharacteristicValue.Length];
DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(hrData);
var hrValue = ProcessData(hrData);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Status.Text = hrValue.ToString();
});
}
}
private int ProcessData(byte[] data)
{
// Heart Rate profile defined flag values
const byte heartRateValueFormat = 0x01;
byte currentOffset = 0;
byte flags = data[currentOffset];
bool isHeartRateValueSizeLong = ((flags & heartRateValueFormat) != 0);
currentOffset++;
ushort heartRateMeasurementValue;
if (isHeartRateValueSizeLong)
{
heartRateMeasurementValue = (ushort)((data[currentOffset + 1] << 8) + data[currentOffset]);
currentOffset += 2;
}
else
{
heartRateMeasurementValue = data[currentOffset];
}
return heartRateMeasurementValue;
}
}

How properly play an audio file to SKYPE4COM

I'm developing the skype plugin. It should play an audio file during the call.
Audio player use naudio library
public class AudioPlayback : IDisposable, IPlayer
{
WaveStream _outStream;
IWavePlayer _player;
IWaveIn _recorder;
public event Action<byte[], int> DataAvailable;
public AudioPlayback()
{
_recorder = new WaveInEvent();
_recorder.WaveFormat = new WaveFormat(16000, 16, 1);
_recorder.DataAvailable += OnRecorderDataAvailable;
}
private void OnRecorderDataAvailable(object sender, WaveInEventArgs e)
{
if (DataAvailable!= null)
{
DataAvailable(e.Buffer, e.BytesRecorded);
}
}
public void LoadFile(string fileName)
{
_outStream = new Mp3FileReader(fileName);
if (_outStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm)
{
_outStream = WaveFormatConversionStream.CreatePcmStream(_outStream);
}
}
private void CreatePlayer()
{
if (_player == null)
{
var waveOut = new WaveOut();
waveOut.DesiredLatency = 200;
waveOut.NumberOfBuffers = 2;
waveOut.DeviceNumber = 0;
_player = waveOut;
}
}
public void Play()
{
CreatePlayer();
if (_player.PlaybackState != PlaybackState.Playing)
{
if (_player.PlaybackState == PlaybackState.Stopped)
_recorder.StartRecording();
_player.Init(_outStream);
_player.Play();
}
}
}
In skype plugin class I create NetworkStream and TcpListener. Use event from player to get buffer data and write to the network stream
WriteToStream(buffer, 0, num);
On call started I change input for skype
call.InputDevice[TCallIoDeviceType.callIoDeviceTypeSoundcard] = "";
call.InputDevice[TCallIoDeviceType.callIoDeviceTypePort] = _inputPort.ToString();
Was fighting with this for several hours. Finally got the sound on the another skype only when turn on Stereo Mixer (Recording devices).
The question: is this the right way? I don't like a bit to play sound and capture it. But here I have a positive thing - I capture exactly with parameters appropriate for skype.

Android.Media.AudioTrack.GetMinBufferSize Method - how to use its syntax in Xamarin.Android (c#)?

I am currently making a music app for Android in Xamarin studio using csharp. I am making a simple synthesizer app and at the moment I am stuck with GetMinBufferSize method with csharp.
Xamarin.Android documentation provides the following syntax for the GetMinBufferSize method (here's the link: xamarin API audiotrack documentation:
[Android.Runtime.Register("getMinBufferSize", "(III)I", "")]
public static int GetMinBufferSize (int sampleRateInHz,
[Android.Runtime.GeneratedEnum] ChannelOut channelConfig,
[Android.Runtime.GeneratedEnum] Encoding audioFormat)
which corresponds to the following in Java (link: android reference):
public static int getMinBufferSize (int sampleRateInHz, int channelConfig, int audioFormat)
The thing I do not understand is what are theses things and how I should use them:
[Android.Runtime.Register("getMinBufferSize", "(III)I", "")]
[Android.Runtime.GeneratedEnum]
[Android.Runtime.GeneratedEnum]
The code in Java was easier:
int buffsize = AudioTrack.getMinBufferSize(_sampleRate,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
where _sampleRate is int _sampleRate = 44100; and represents frequency rate.
So, if you at least told me what those three lines in brackets from xamarin documentation are - I would be so grateful.
Thank you in advance and have a great day.
My code so far:
namespace simple_synth
{
[Activity (Label = "_secondAct")] //activity that opens the second screen
public class _secondAct : Activity
{
Thread _thread; //audio processing thread
int _sRate = 44100; //sampling rate
bool isRunning = true; //switch on/off
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout._secondLay);
Button btn2 = FindViewById<Button> (Resource.Id.myButton_synth);
_audio _audioSound = new _audio ();
btn2.Click += (sender, e) => {
btn2.Text = "GOOD";
Thread _audioThread = new Thread(_audioSound._makeSound);
_audioThread.Start();
Console.WriteLine("audio thread: started");
while (!_audioThread.IsAlive);
Thread.Sleep(1000);
_audioSound._stopRequest();
_audioThread.Join();
Console.WriteLine("audio thread: terminated now!");
_audioSound._startRequest();
};
}
}//_secondAct
public class _audio{
private volatile bool _stopItNow;
public void _makeSound(){ // This method will be called when the thread is started.
while (!_stopItNow) {
Console.WriteLine ("audio thread: is playing the sound...");
AudioTrack _audioTrack = new AudioTrack (Stream.Music, 22050,
ChannelConfiguration.Mono,
Android.Media.Encoding.Pcm16bit,
_audBuffer.Length, AudioTrackMode.Stream);
_audioTrack.Play ();
_audioTrack.Write (_audBuffer, 0, _audBuffer.Length);
}
Console.WriteLine ("audio thread: terminated.");
} //doWork
public void _stopRequest()
{
_stopItNow = true;
}
public void _startRequest()
{
_stopItNow = false;
}
}
}
Very simple in C# as well:
var minBufSize = AudioTrack.GetMinBufferSize (
44100,
ChannelOut.Mono,
Encoding.Pcm16bit);

Virtual scanner (TWAIN) not working in C# (WPF)

It is about TWAINdotNet library. I have spent last 24 hours trying to do basic virtual scanner experiment in C#/WPF/VS2010. I have already downloaded and installed virtual scanner driver from http://sourceforge.net/projects/twain-samples/files/ and it appears just fine in the list of available TWAIN data sources. Interestingly, the sample application that is available on this page works perfectly fine with this driver too. The problem occurs only when I try to use it through C#/WPF.
Specifically, calling DsUserInterface using Message.EnableDS fails for God-knows what reason. It fails in all cases whether I ask it to show UI or not. Similarly DsImageLayout call also results in Failure when trying to set the scan area. Last but not the least, trying to set measurement units to inches (or whatever) also doesn't take effect. The call doesn't fail, but the previous value remains intact.
Here's the code in case I may be doing something wrong:
public partial class MainWindow : Window
{
TwainDotNet.Wpf.WpfWindowMessageHook mTwnHook;
TwainDotNet.Twain mTWN;
TwainDotNet.ScanSettings setting = new TwainDotNet.ScanSettings();
public MainWindow()
{
InitializeComponent();
}
private void btnScan_Click(object sender, RoutedEventArgs e)
{
InitializeTWAIN();
mTWN.ScanningComplete += twn_ScanningComplete;
mTWN.TransferImage += twn_TransferImage;
mTWN.StartScanning(setting);
}
private void InitializeTWAIN()
{
mTwnHook = new TwainDotNet.Wpf.WpfWindowMessageHook(this);
mTWN = new TwainDotNet.Twain(mTwnHook);
setting.UseAutoFeeder = true;
setting.UseDocumentFeeder = true;
setting.UseDuplex = true;
setting.TransferCount = 1;
setting.Page = new TwainDotNet.PageSettings()
{
Orientation = TwainDotNet.TwainNative.Orientation.Auto,
Size = TwainDotNet.TwainNative.PageType.UsLetter
};
setting.Area = new TwainDotNet.AreaSettings(TwainDotNet.TwainNative.Units.Millimeters, 0f, 0f, 279.4f, 215.9f);
setting.Resolution = new TwainDotNet.ResolutionSettings()
{
ColourSetting = TwainDotNet.ColourSetting.Colour,
Dpi = 100
};
setting.ShouldTransferAllPages = true;
setting.ShowTwainUI = false;
}
void twn_TransferImage(object sender, TwainDotNet.TransferImageEventArgs e)
{
//save image
}
void twn_ScanningComplete(object sender, TwainDotNet.ScanningCompleteEventArgs e)
{
if (e.Exception != null)
MessageBox.Show(e.Exception.Message);
}
}

Categories