wallner
Posts: 1
Joined: Mon Feb 11, 2013 6:01 pm

Libftdi dual usb-serial problen

Mon Feb 11, 2013 6:32 pm

Hello!
Firstly, i'm not really sure if this is the correct place to post on, feel free to move if wrong.

I have a pie (512mb), which i intend to use for controlling a DMX512 usb-serial interface that needs to have a baudrate of 250000 (non standard) and another usb-serial connected to a led-sign that runs on baudrate 9600.
However, due to the DMX non standard baudrate i am to my knowledge bound to use the libftdi library.
Sadly, the library needs to pull the ftdi_sio driver and i'm not able to differentiate the controllers through the library, thus attaching correct program to the correct port very complicated

Is there any other approach (maybe that avoids pulling the kernel driver)?
I have searched for weeks and can't find a solution...

Running a buildroot system.

wollik
Posts: 10
Joined: Thu Dec 20, 2012 7:16 pm

Re: Libftdi dual usb-serial problen

Fri Feb 15, 2013 7:05 pm

Hi Wallner,
I've played a lot with my different systems to figure out how to set a custom baud rate also for an USB converter port. So far I can only get the USB Converters with the FTDI Chip (ftdi_sio.ko driver module) to do the job like I need it.

You don't have to use a special lib, just use one of the newer raspi kernels.

To set a non standard baudrate just set these parameters via setserial:
spd_cust (tells the driver to use a baud rade calculated by the divisor related o the base_baud)
divisor (sets the divisor to a fixed value)

Here is my example what you need to do for your baud rate

Code: Select all

pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # Example for custom baud of 250000
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # 1) Find the port with the ftdi chipset:
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ dmesg | grep ttyUSB
[    6.413568] usb 1-1.2.2: pl2303 converter now attached to ttyUSB0
[    6.592745] usb 1-1.2.4: pl2303 converter now attached to ttyUSB1
[    7.365532] ftdi_sio ttyUSB2: Unable to read latency timer: -32
[    7.374213] ftdi_sio ttyUSB2: Unable to write latency timer: -32
[    7.394790] usb 1-1.3: [b]FTDI [/b]USB Serial Device converter now attached to [b]ttyUSB2[/b]
[  388.187559] ftdi_sio ttyUSB2: Unable to write latency timer: -32
[  388.370679] ftdi_sio ttyUSB2: Unable to write latency timer: -32
[  588.110418] ftdi_sio ttyUSB2: Unable to write latency timer: -32
[  588.294418] ftdi_sio ttyUSB2: Unable to write latency timer: -32
pi@raspberrypi ~/tools $
pi@raspberrypi ~/tools $
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # So we will use /dev/ttyUSB2
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # Read out the base_baud of the ftdi chipset by:
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ setserial -a /dev/ttyUSB2
/dev/ttyUSB2, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
        [b]Baud_base: 24000000[/b], close_delay: 0, divisor: 7500
        closing_wait: infinite
        Flags: spd_normal low_latency

pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # Next set for non standard baud
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ setserial -a /dev/ttyUSB2 spd_cust
pi@raspberrypi ~/tools $
pi@raspberrypi ~/tools $ setserial -a /dev/ttyUSB2
/dev/ttyUSB2, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
        Baud_base: 24000000, close_delay: 0, divisor: 7500
        closing_wait: infinite
        Flags: [b]spd_cust[/b] low_latency

pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # Calculate the divisor by dividing Baud_base / Cust_Baud
pi@raspberrypi ~/tools $ # 24000000 / 250000
pi@raspberrypi ~/tools $
pi@raspberrypi ~/tools $ # set the divisor for the ftdi chip to 96
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ setserial -a /deb/ttyUSB2 divisor 96
/deb/ttyUSB2: No such file or directory
pi@raspberrypi ~/tools $ setserial -a /dev/ttyUSB2 divisor 96
pi@raspberrypi ~/tools $ setserial -a /dev/ttyUSB2
/dev/ttyUSB2, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
        Baud_base: 24000000, close_delay: 0, divisor: [b]96[/b]
        closing_wait: infinite
        Flags: [b]spd_cust[/b] low_latency

pi@raspberrypi ~/tools $
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ # activate the new baud by specify 38400 baut to the port
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ #
pi@raspberrypi ~/tools $ stty -F /dev/ttyUSB2 38400
------- Will give an error because we are using our own speed, but this must be done to activate the customized speed in the chipset!
/code]

You can use your terminal program to set the baud to 38400 and you can also put other line set characteristics, or you can use stty.

Here is a smal script I'm using to change my USB converters to a non standard baud.  Try it out it is mainy used on my FritzBox, where I also have to load the driver modules, but runs fine under Raspbery too.


Regards
WolliK

P.S. I neither can attach shell scripts or text files, so send me a short e-mail and I'll forward it to you
Last edited by wollik on Mon May 12, 2014 8:33 pm, edited 1 time in total.

richardash1981
Posts: 4
Joined: Sat Feb 09, 2013 5:02 pm

Re: Libftdi dual usb-serial problen

Sat Feb 22, 2014 9:08 pm

I know you are after using an external USB serial device, but I thought I would share the C code I have devised to set the internal UART of the pi to 250kbaud. Trying this with python-serial does not work!.

To make this work, you will need to raise the Pi's UART clock, because the default one maxes out at 115kbaud. So you will need to add

Code: Select all

init_uart_clock=16000000
to the /boot/config.txt file on the system. This won't affect any other user of the serial port provided you have a recent kernel.

This code is vaguely based on something from dmx4linux. I'm hoping eventually to turn this into a proper ola plugin, but it should work for whatever custom baud rates you need your Pi to do!

Code: Select all

/*
 * Copyright (C) Michael Stickel <michael@cubic.org>
 * Copyright (C) 2014 Richard Ash <richardashaudacity@googlemail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */

/* This file includes <asm/ headers for Linux, which are very prone to
conflicts
 * so do as little as possible here, with as few headers as possible
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// this provides ioctl() definition without conflicting with
// asm/termios.h afterwards
#include <stropts.h>
// use this not standard termios for custom baud rates
#include <asm/termios.h>

int set_DMX_baud_linux(int fh, int verbose)
{
   struct termios2 tio;   // linux-specific terminal stuff

   const int rate = 250000;

   if (fh==-1) return -1;

   /* Set up custom speed for UART */
   if (ioctl(fh, TCGETS2, &tio) < 0)	// get current uart state
       return -1;
   tio.c_cflag &= ~CBAUD;
   tio.c_cflag |= BOTHER;
   tio.c_ispeed = rate;
   tio.c_ospeed = rate;		// set custom speed directly
   if (ioctl(fh, TCSETS2, &tio) < 0)	// push uart state
       return -1;
   if (verbose > 1)
      {	// if verbose, read and print
      if (ioctl(fh, TCGETS2, &tio) < 0)	// get current uart state
         {
         fprintf(stderr, "Error getting altered settings from port\n");
		 }
	  else
         {
         fprintf(stderr, "Port speeds are %i in and %i out\n", 
            tio.c_ispeed, tio.c_ospeed);
		 }
	  }

   return 0;
}

bleem313
Posts: 2
Joined: Tue Jun 10, 2014 10:18 pm

Re: Libftdi dual usb-serial problen

Tue Jun 10, 2014 10:26 pm

richardash1981, I was wondering if you could help me out, using your code, this is what I came up with

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <stropts.h>
#include <asm/termios.h>

int set_DMX_baud_linux(int fh, int verbose)
{
   struct termios2 tio;   // linux-specific terminal stuff

   const int rate = 250000;

   if (fh==-1) return -1;

   /* Set up custom speed for UART */
   if (ioctl(fh, TCGETS2, &tio) < 0)   // get current uart state
       return -1;
   tio.c_cflag &= ~CBAUD;
   tio.c_cflag |= BOTHER;
   tio.c_ispeed = rate;
   tio.c_ospeed = rate;      // set custom speed directly
   if (ioctl(fh, TCSETS2, &tio) < 0)   // push uart state
       return -1;
   if (verbose > 1)
      {   // if verbose, read and print
      if (ioctl(fh, TCGETS2, &tio) < 0)   // get current uart state
         {
         fprintf(stderr, "Error getting altered settings from port\n");
       }
     else
         {
         fprintf(stderr, "Port speeds are %i in and %i out\n", 
            tio.c_ispeed, tio.c_ospeed);
       }
     }

   return 0;
}

int main (void){
	int uart0_filestream = -1;
	uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);		//Open in non blocking read/write mode
	if (uart0_filestream == -1)
	{
		//ERROR - CAN'T OPEN SERIAL PORT
		printf("Error - Unable to open UART.  Ensure it is not in use by another application\n");
	}
	set_DMX_baud_linux(uart0_filestream, 2);
	for(;;)
	if (uart0_filestream != -1)
	{
		// Read up to 255 characters from the port if they are there
		unsigned char rx_buffer[256];
		int rx_length = read(uart0_filestream, (void*)rx_buffer, 255);		//Filestream, buffer to store in, number of bytes to read (max)
		if (rx_length < 0)
		{
			//An error occured (will occur if there are no bytes)
		}
		else if (rx_length == 0)
		{
			//No data waiting
		}
		else
		{
			//Bytes received
			rx_buffer[rx_length] = '\0';
			printf("%i bytes read : %s\n", rx_length, rx_buffer);
		}
	}
	return 0;
}
When I run this, I get the program tell me the port speeds are 250000 in and out, but then nothing ever prints when I try and send dmx commands to it. I have an FTDI adapter hooked to my laptop and Artemis sending dmx commands to it. The FTDI adapter is hooked to the serial pins of the pi.

I know the FTDI adaptor and Artemis are working perfectly, as I have hooked it to an arduino setup to receive dmx as 250000, and I get the info perfectly.

Any help you could give me would be much appreciated.

bleem313
Posts: 2
Joined: Tue Jun 10, 2014 10:18 pm

Re: Libftdi dual usb-serial problen

Wed Jun 11, 2014 12:32 am

Actually, I found out it IS working, sorta.

All the data received seems to also be sent back out on tx (not sure why, wish it didn't, but not a huge problem)

The read function seems to only read once a line feed has been sent, which won't work for me as line feeds aren't part of dmx.

Once again, any help would be apreciated


Return to “Bare metal, Assembly language”