Problem:
I have USB devices connected to a remote linux machine. I would like to reset them using file descriptors.
I connect to a port using generic port names in /dev/usbTTYXX. Unfortunately, I quickly found out this was a bad approach as these are generated in order. If I plugged in a tty device first it will generate ttyUSB0 and if I plugin a second tty device it will generate TTYUSB1 and so on. Unfortunately I have too many different ttyUSB devices and others that break this order. In short its just not user friendly and is a nightmare. I found that it is better to open a port using specific simlink file descriptors in /dev/serial/by-id. This is best preferred since they seem very unique and do not change even after restart, reboot despite order of USB plugged in.
So I can open a port in a more robust way like so. (I even have a json for this)
// old
int serial_port = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY);
// new
int serial_port = open("/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AC00MET6-if00-port0", O_RDWR | O_NOCTTY);
No matter how much I reconnect, the USB device will not change (unlike /dev/ttyUSB0). Anyways I found this code that potentially performs a soft-reset to a device so I do not need to replug it in. Here is the source:
If I use this file descriptor /dev/bus/usb/001/010 it works. /dev/bus/usb/XXX/YYY where XXX is the bus number (nearly always 001 on the Pi) and YYY is the device number (get both of these from lsusb). Again lsusb also seems to change quite often. (Even more troublesome, I have similar device adapters for the USB which use the same Product and Vendor ID!)
However it will not work if I use /dev/ttyUSB0 or by id with /dev/serial/by-id/. The error I get is Error in ioctl: Inappropriate ioctl for device..
Question: How can I use the ioctrl USBDEVFS_RESET method with the /dev/serial/by-id/ file simlinks?
/* usbreset -- send a USB port reset to a USB device */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
close(fd);
return 0;
}
I am trying to write from the Serial Port to an SD Card in my Arduino Mega 2560, using a card module.
I want to be able to write in a txt file what I type in the serial com.
#include <SPI.h>
#include <SD.h>
const int chipSelect = 4;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.print("This is a test and should be ignored");
if (!SD.begin(chipSelect)) {
Serial.println("\nCard failed, or not present");
// don't do anything more:
return;
}
else{
Serial.println("\ncard initialized.");
}
}
void loop() {
// put your main code here, to run repeatedly
File OpenFile = SD.open("test.txt", FILE_WRITE);
if(OpenFile and Serial.available());
{
OpenFile.println(Serial1.read());
OpenFile.close();
}
}
However a continous line of "-1" and "1", without the ", is written to the SD.
Yes, I am able to write to the SD card through other methods...
Cheers, PoP
I notice you are checking Serial.available() but using Serial1 to read from :)
As you have a Mega, you wouldn't get an error as there is Serial and Serial1. I'd say this is your culprit!
The Stream read function will return -1 when there is no data. Also you could lessen the load on your Arduino and do the operation all at once (not open/close for each byte) and purge all available data (Serial.read() only reads a single byte in case you did not know).
void loop() {
File OpenFile = SD.open("test.txt", FILE_WRITE);
if(OpenFile){
while(Serial.available()){
OpenFile.println(Serial.read());
}
OpenFile.close();
}
}
You may want to check if the SD lib supports appending by default or a flag like FILE_APPEND as you will overwrite the file on the next loop if more data becomes available (Serial data isn't instant, your code may loop while receiving the rest of the data).
I am trying JackAudio with c++ on Windows 8.1 and it works.
I am using a simple client code that can be found on the git. This code should send a low pitch signal to one hear and a high pitch signal to the other but for me it sends both signals to both hear.
I don't know what is wrong since two are registered and both get access to the correct speakers.
/** #file simple_client.c
*
* #brief This simple client demonstrates the basic features of JACK
* as they would be used by many applications.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <jack/jack.h>
jack_port_t *output_port1, *output_port2;
jack_client_t *client;
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
static void signal_handler(int sig)
{
jack_client_close(client);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}
/**
* The process callback for this JACK application is called in a
* special realtime thread once for each audio cycle.
*
* This client follows a simple rule: when the JACK transport is
* running, copy the input port to the output. When it stops, exit.
*/
int
process(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *out1, *out2;
paTestData *data = (paTestData*)arg;
int i;
out1 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port1, nframes);
out2 = (jack_default_audio_sample_t*)jack_port_get_buffer(output_port2, nframes);
for (i = 0; i<nframes; i++)
{
out1[i] = data->sine[data->left_phase]; // left
out2[i] = data->sine[data->right_phase]; // right
data->left_phase += 1;
if (data->left_phase >= TABLE_SIZE) data->left_phase -= TABLE_SIZE;
data->right_phase += 10; // higher pitch so we can distinguish left and right.
if (data->right_phase >= TABLE_SIZE) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/**
* JACK calls this shutdown_callback if the server ever shuts down or
* decides to disconnect the client.
*/
void
jack_shutdown(void *arg)
{
exit(1);
}
int
main(int argc, char *argv[])
{
const char **ports;
const char *client_name;
const char *server_name = NULL;
jack_options_t options = JackNullOption;
jack_status_t status;
paTestData data;
int i;
/*if (argc >= 2) { // client name specified?
client_name = argv[1];
if (argc >= 3) { // server name specified?
server_name = argv[2];
int my_option = JackNullOption | JackServerName;
options = (jack_options_t)my_option;
}
}
else { // use basename of argv[0]
client_name = strrchr(argv[0], '/');
if (client_name == 0) {
client_name = argv[0];
}
else {
client_name++;
}
}*/
client_name = "mytest";
for (i = 0; i<TABLE_SIZE; i++)
{
data.sine[i] = 0.2 * (float)sin(((double)i / (double)TABLE_SIZE) * M_PI * 2.);
}
data.left_phase = data.right_phase = 0;
// open a client connection to the JACK server
client = jack_client_open(client_name, options, &status, server_name);
if (client == NULL) {
fprintf(stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
if (status & JackServerFailed) {
fprintf(stderr, "Unable to connect to JACK server\n");
}
exit(1);
}
if (status & JackServerStarted) {
fprintf(stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
client_name = jack_get_client_name(client);
fprintf(stderr, "unique name `%s' assigned\n", client_name);
}
// tell the JACK server to call `process()' whenever
//there is work to be done.
jack_set_process_callback(client, process, &data);
// tell the JACK server to call `jack_shutdown()' if
//it ever shuts down, either entirely, or if it
//just decides to stop calling us.
jack_on_shutdown(client, jack_shutdown, 0);
// create two ports
output_port1 = jack_port_register(client, "output1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
output_port2 = jack_port_register(client, "output2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ((output_port1 == NULL) || (output_port2 == NULL)) {
fprintf(stderr, "no more JACK ports available\n");
exit(1);
}
//Tell the JACK server that we are ready to roll. Our
// process() callback will start running now.
if (jack_activate(client)) {
fprintf(stderr, "cannot activate client");
exit(1);
}
// Connect the ports. You can't do this before the client is
// activated, because we can't make connections to clients
// that aren't running. Note the confusing (but necessary)
// orientation of the driver backend ports: playback ports are
// "input" to the backend, and capture ports are "output" from
// it.
ports = jack_get_ports(client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if (ports == NULL) {
fprintf(stderr, "no physical playback ports\n");
exit(1);
}
if (jack_connect(client, jack_port_name(output_port1), ports[0])) {
fprintf(stderr, "cannot connect output ports\n");
}
if (jack_connect(client, jack_port_name(output_port2), ports[1])) {
fprintf(stderr, "cannot connect output ports\n");
}
jack_free(ports);
// install a signal handler to properly quits jack client
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif
// keep running until the Ctrl+C
while (1) {
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
jack_client_close(client);
exit(0);
}
Did you ever figure this out? I'm quite new to coding with and configuring Jack myself but my hunch is, the problem is not in the code, rather it's a mixer issue. I suspect there's a setting somewhere that has put the jack server in a mono mode of sorts which would mean all output streams are multed (yes spell checker, multed is a word in the audio engineering world :) ) to all physical audio outputs. So... stream 1 would be connected to the left and right physical output, and stream 2 would also be connected to the physical left and right outputs.
There is nothing anywhere that would necessarily say that stream 1 goes to the left output and stream 2 goes to the right... in fact, if you're running an SDDS configuration the first stream might be the left output, and the 2nd might be the left center... you wouldn't get to the right channel until you hit the 5th stream (with the 2nd, 3rd, and 4th being left center, center, and right center respectively).
Again, this is just a guess but check to see if there's a mixer or "patch bay" style application on your platform that allows you to route streams to physical outputs. In the meantime, I'll give this code a go on my system (Debian unstable/w experimental 4.3 kernel) to see what happens.
Cheers, Joe
Pardon, me - it's an old question, but for the benefit of whoever reads it... I tested this program on my System and found it works correctly!
Question to the original poster: Would you object to having this example included in the JackD example repository (https://github.com/jackaudio/example-clients)? I feel that it's a very good example on how to use the audio streaming part of the JackD API. It would probably need some small rewrite as a generic platform C program; it would be under the same license as the other examples in the JackD example repo (GPL 2). I've sent a mail to the JackD developer's list (jack-devel#lists.jackaudio.org) asking what they think.
Anyway - shewhorn had the correct hunch - nothing wrong with your code, but when you tested your program there was something wrong with the port mappings on your system (i.e. how the ports were mapped to the physical ports on your soundcard). The way to fix it is outside your application: Use some mixer or patch bay style application to route your program's streams correctly. Not your (code's) fault, your program works fine and does what you intended.
I installed the ftdilib and I am trying to compile this code:
/* hello-ftdi.c: flash LED connected between CTS and GND.
This example uses the libftdi API.
Minimal error checking; written for brevity, not durability. */
#include <stdio.h>
#include <ftdi.h>
#define LED 0x08 /* CTS (brown wire on FTDI cable) */
int main()
{
unsigned char c = 0;
struct ftdi_context ftdic;
/* Initialize context for subsequent function calls */
ftdi_init(&ftdic);
/* Open FTDI device based on FT232R vendor & product IDs */
if(ftdi_usb_open(&ftdic, 0x0403, 0x6001) < 0) {
puts("Can't open device");
return 1;
}
/* Enable bitbang mode with a single output line */
ftdi_enable_bitbang(&ftdic, LED);
/* Endless loop: invert LED state, write output, pause 1 second */
for(;;) {
c ^= LED;
ftdi_write_data(&ftdic, &c, 1);
sleep(1);
}
}
but there is error: ftdi_enable_bitbang was not declared in this scope
This is the only error.
Why does this keep to pop out?
One quick look into the current version of ftdi.h shows there is no declaration for ftdi_enable_bitbang. ftdi_enable_bitbang has been removed after being deprecated for two years. Use ftdi_set_bitmode instead.
I have two sketches I am running on an Arduino Uno. The first one dumps a file to the serial if it exists. This is one of the examples that comes with the Arduino, but I've modified it as such:
/*
SD card file dump
This example shows how to read a file from the SD card using the
SD library and send it over the serial port.
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
Created 22 December 2010 by Limor Fried
Modified 9 Apr 2012 by Tom Igoe
This example code is in the public domain.
*/
#include <SD.h>
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect. Needed for Leonardo only.
}
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// Don't do anything more:
return;
}
Serial.println("card initialized.");
// Open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt");
// If the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
Serial.write(dataFile.read());
}
dataFile.close();
}
// If the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
void loop()
{
}
My other sketch is supposed to remove a file. When I run this remove sketch it says there is no file found. Yet I can continually run the above sketch and dump the contents to the serial. My remove sketch is as follows:
#include <SD.h>
const int chipSelect = 4;
void setup(){
Serial.begin(115200);
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
if(SD.exists("datalog.txt"))
{
SD.remove("datalog.txt");
Serial.println("file removed");
}
else
{
Serial.println("no file to remove");
}
}
void loop(){
}
Am I missing something here?
Just after posting this I realized I was not making this remove sketch fault tolerant and added the following code after the pinmode line:
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
Thus the new remove sketch was as follows:
#include <SD.h>
const int chipSelect = 4;
void setup(){
Serial.begin(115200);
Serial.print("Initializing SD card...");
// Make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// See if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// Don't do anything more:
return;
}
Serial.println("card initialized.");
if(SD.exists("datalog.txt"))
{
SD.remove("datalog.txt");
Serial.println("file removed");
}
else
{
Serial.println("no file to remove");
}
}
void loop(){
}
Upon running that sketch it now removes the files. Why is it that new version works but the old one did not?
Adding SD.begin() doesn't make it fault tolerant. It initializes the library. You need to call that before calling other functions. From the Reference:
begin() Initializes the SD library and card. This begins use of the
SPI bus (digital pins 11, 12, and 13 on most Arduino boards; 50, 51,
and 52 on the Mega) and the chip select pin, which defaults to the
hardware SS pin (pin 10 on most Arduino boards, 53 on the Mega).