GPIO in IO expansion board for Edison from DFROBOT - gpio

I have been using Intel Edison Module for my project along with this IO expansion Board from DFRobot.
But I came across a problem when dealing with the GPIOs: the output level seems to be quite unstable compared with the Arduino-Compatible Board.
Here is what I did to use DIO7 as output for both IO borads (called X-board and Arduino-board):
According to this document, for the Arduino-borad, I first set an internal GPIO 255 to high so I can use GPIO48 (mapped to DIO7) as an output. Then I set GPIO 48 to high or low. Everything turns out OK.
echo 255 > /sys/class/gpio/export
echo 48> /sys/class/gpio/export
echo high > /sys/class/gpio/gpio255/direction
echo high or low > /sys/class/gpio/gpio48/direction
On the X-board, the procedure is quite straightforward. I set GPIO 48 to high or low directly.
echo 48> /sys/class/gpio/export
echo high or low > /sys/class/gpio/gpio48/direction
But when I monitor the voltage using an oscilloscope, the pin level on the Arduino-board is quite stable and fluctuates in a small range (10mV) while the one on X-board vibrates in 20MHz between 1-5V (sometimes 0-3V and sometimes stable), which is unacceptable.
I also try using mraa, but also no luck.
Does anybody know where is the problem or what have I missed? Any comment or suggestion will be appreciated.

Related

Beaglebone black GPIO registers not changing voltage on value change

I'm trying to turn on and off the GPIO headers on the beaglebone, but i'm unable to get the physical pins to switch from high to low and vice versa. Ive written some code within my application to do this but even when I change the values in the command line I have the same issues.
Firstly, all of the pins I want to use have been correctly exported. For this example lets focus on GPIO 117. I'm able to change into /sys/class/gpio/gpio117 and when I run cat value, its in line with what I expected from my program. When I run echo 0 > value it changes to a zero and when I run echo 1 > value its a 1. Everything as expected. When I go to measure the voltage on that pin, it is always high, independent of the value.
Am I missing something here?
GPIO 117 is gpio3_21 on the "MCSAP0_AHCLKX" pin. So it is probably used by some audio device, probably HDMI. You can disable that by adding disable_uboot_overlay_audio=1 to your /boot/uEnv.txt file, see https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Disable_on-board_devices

What's the maximum baud rate in MATLAB?

Ubuntu 16.04 & MATLAB R2017a.
I'm trying to set serial port like that:
s=serial_port('/dev/ttyUSB0','BaudRate',115200,'DataBits',8,'InputBufferSize',80000)
It's working fine, but when I try to change baud rate, say 1000000.
I got this message:
Open failed: BaudRate could not be set to the specified value.
So, I have 2 question:
1) Is it possible to set not common baud rates, say 2000000?
2) I found, that 1500000 and 3000000 is working for me.
Is there maximum speed?
** UPDATE**
I know how to change the baud rate in OS, in my case (Ubuntu 16.04)
setserial is not working, so I'm using sudo stty -F /dev/ttyUSB3 3500000 (not all speed is allowed) or via asm/termios.h> -- all speed is allowed.
So, I'm using second way.
After that, I can easily listen the port like that cu -l /dev/ttyUSB0
And at the same time I cant set the speed in matlab.. (Error above)
Although this link should provide you enough information about how to manage baud rates on Matlab side, as #Cris Luengo already stated in his command, I would like to elaborate a little bit on the hardware side of the problem.
Using the following command:
stty -F /dev/ttyUSB0
you should be able to retrieve the current baud rate of the targeted device. Alternatively, the following command also retrieves that value:
setserial -ag /dev/ttyUSB0
together with other important information:
/dev/ttyUSB0, Line ..., UART: ..., Port: ..., IRQ: ...
Baud_base: ..., close_delay: ..., divisor: ...
closing_wait: ..., closing_wait2: ...
Flags: ...
OS side, you can play with the baud rate of some devices but if you want to avoid problems, you always have to set a coherent value when establishing a connection. Generally speaking, devices have a tolerance level (of, I think, no more than ±5%) on overspeed and underspeed concerning baud rate deviance... so you can try to force an arbitrary baud rate different from the current one, but you don't want to go too far from it.

Register address - change bit value of the second bit (bit index = 1) to 1

i am having the following register address: 0x18040028. Since I am pretty new to that stuff, how am I supposed to access that register address, change that one bit and then write it back (all other entries should stay the same)?
Do I need to write a program, or can I do it from the terminal ?
I am doing that on a linux (openwrt)
thanks
Option 1
On many linux builds you can access the GPIO pins directly using the sysfs. On openwrt in particular it is nearly always exposed.
on the openwrt device's terminal, see if this folder exists:
ls -Al /sys/class/gpio
If it is there, you usually need to export the specific GPIO pin you want to access. I looked at http://www.black-swift.ru/files/AR9331.pdf and can't figure it out. The problem is I don't think that particular pin on that register is exposed that way - at least I can't find it. I would have to be on that system digging around in the GPIO controller to have a chance to figure it out.
The UART pins you want to enable are exposed - GPIO9 (RX) and GPIO10 (TX). So maybe this info will be helpful regardless.
Option 2, below, is pretty much guaranteed to work; I found that after I had written this part.
Depending on your kernel version, you either use that GPIO # directly, or add in an offset.
Try:
cat /sys/class/gpio/gpiochip*/base | head -n1
If it returns a number, thats the offset. Take your GPIO #, add that offset (making up 200 as an example) and use that as your GPIO #.
Using whatever your GPIO number is (either with or without offset), enter the following (using 210 just as an example; 200 offset, GPIO10)
echo "210" > /sys/class/gpio/export
then the GPIO pin will exposed in this directory, again using 210 as example, /sys/class/gpio210/
There will be at least two files created after the export, /sys/class/gpio240/value and /sys/class/gpio240/direction You can interact with them using cat to read them, e.g. cat /sys/class/gpio240/value and modify it using echo: echo 1 > /sys/class/gpio240/value
There is a lot more info on accessing gpio via sysfs in the links I put at the bottom.
This will work easily if you find the right GPIO #, but if not (or even if you do), use:
Option 2
Someone has already done all the work. There are instructions on how to interface with this register to disable / enable the UART. It requires adding a package to your openwrt install called io, and they provide a script that toggles the value of the bit. You can modify that if you want to just echo out, always set it to a certain value, etc. It's written in bash.
You can add either the contents of the script or call the script itself from /etc/rc.local and it will get run at each boot; addressing that concern.
Since you already know you have the AR9331, you can cut out a lot of the script, e.g.:
#!/bin/bash -
# Bitwise operations: & = And, | = Or, ^ = xOr, << = Left Shift
func_addr="0x18040028"
func_value=0x`io -4 $func_addr | cut -f3 -d'
case_bit="1<<1"
# This is where you would make a change if you wanted to
# just set it to 1 every time.
# To always set it to a '1', change from xor ^ to or |; like this
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value | $case_bit)))
# to always be 0 change the operator to and &, and use a mask
# with just bit 1 set to 0
mask32_b1="0xFFFFFFFD"
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value $ $mask32_b1)))
# we using Bitwise xOr operation to switching bit# state (0 or 1)
io -4 $func_addr $(printf "0x%8.8x" $(($func_value ^ $case_bit)))
# read bit# state and depending on the state - print some info
if [ $(($func_value & $case_bit)) = $(($case_bit)) ]; then
echo "Hardware UART is turned OFF"
# You can use this line for automatic configuring GPIOs via sysfs
# or you can load other modules that use these GPIOs
else
echo "Hardware UART is turned ON"
fi
It could be a one liner(fairly ugly one):
io -4 "0x18040028" $(printf "0x%8.8x" $(("0x"$((io -4 "0x18040028" | cut -f3 -d )) ^ "0x2")))
Toggle uart_en on AR9331
I couldn't test any of this, so I could have made a mistake anywhere, but if you follow that guide, and make the modifications to always set to 1 that I put in there (commented out at the moment), then you should be good. Make sure you only leave in one option to modify that register.
Sources / more info:
OpenWrt Wiki
Working with GPIOs
Kernel.org
The quick and dirty way is to try and mmap the memory region out of /dev/mem. See these two questions:
Accessing hardware registers in Linux userspace
Accessing physical address from user space
However, I would not suggest you do this for a production system. What is cleaner would be to write a kernel driver. One option is write a regular kernel module that uses ioremap and ioread/iowrite operations, and exposes the registers via sysfs.
Using IO Memory
Sysfs Documentation
Another option that is particularly slick in my opinion, is to have these registers exposed through the platform_device system in your board support files.
Platform Devices
Basically you need to read the value, and then do:
readvalue |= 1<<1;
Then write the value back to the register.

PWM programming issue in my BBB

Background: Bought a BBB and experimenting a bit, managed to control LEDS and relays.
Problem: can't get the expected behaviour from the servo, it keeps spinning CCW
Cause: don't know, whey I'm asking here :)
Facts:
BBB with Angstrom
External 5V DC to both BBB and servo
Servo: Tower Pro sg90 (very common servo) AND it's working as I tried it in my RC car.
Procedure: following som tutorials on the web (and used Adafruit_BBIO library), I'm trying to make my servo work, e.g. turn 0, 90, 180 etc so here's what I'm doing:
echo am33xx_pwm > /sys/devices/bone_capemgr.8/slots
echo bone_pwm_P8_13 > /sys/devices/bone_capemgr.8/slots
echo 20000000 > /sys/devices/ocp.2/pwm_test_P8_13.15/period (this is 50Hz,also tried 60Hz)
echo 10000000 > /sys/devices/ocp.2/pwm_test_P8_13.15/duty
echo 1 > /sys/devices/ocp.2/pwm_test_P8_13.15/run
Doing the above the servo spins CCW with no stop. I can read 50Hz (60Hz) and 1.66V and even tried to use level shifter so I get ~ 2.5V
I don't know what I'm doing wronge (if I am) or am I missing something?
I also struggled to get a servo working with the Beaglebone Black.
Ultimately, I was able to get good results by exactly following this tutorial: http://learn.adafruit.com/controlling-a-servo-with-a-beaglebone-black?view=all
As I understand it, the most recent versions of the Adafruit_BBIO library handle the pin muxing stuff completely, so your only interface to the BBB can be through a Python script, rather than having to do the command line stuff in your question.
The Adafruit_BBIO library has changed significantly in the last 30 days, so it's worth doing these steps in order:
reboot BBB
run pip install Adafruit_BBIO --upgrade
Try a simple Python script like the one in the tutorial from Adafruit.
I hope this helps!
Update in response to poster's comment:
Hmmm, sorry to hear that my steps didn't work! If your code is resulting in 13% duty cycle at 50 or 60Hz, that makes me think the code is fine, and the servo is having trouble.
I know you've probably checked it a dozen times, but is the 5v you're sending to the servo checking out? As in, is it coming from P9_5 or P9_6, which are from the high-current 5v supply?
Also, re-reading your question, you say the servo keeps spinning CCW - if it doesn't reach a limit and stop moving at some point, there's your problem: continuous-rotation servos aren't able to reach specific set points because they lack the feedback system that 0-180 servos have...
the voltage for the pinuots is 3.3v (except ADC 0-1.8V range (do not exceed!) ) not 5v, so is correct read 1.66v with duty cycle of 50%.
Valid pulse width for "Tower Pro sg90" is 500-2400 µs, so valid values for "duty" are 500000-2400000.
This should turn your servo in CW direction:
// On my BBB, polarity is inverted by default
echo 0 > /sys/devices/ocp.2/pwm_test_P8_13.15/polarity
echo 20000000 > /sys/devices/ocp.2/pwm_test_P8_13.15/period
echo 500000 > /sys/devices/ocp.2/pwm_test_P8_13.15/duty
echo 1 > /sys/devices/ocp.2/pwm_test_P8_13.15/run

Beaglebone gpio input not working

I am using beaglebone to access digital input from specific pin using sysfs interface. And I can change the output states but not the input :(. What I did is, I have two pins pinA and pinB. pinA I made it output and pinB I made input. Connected pinA to pinB. Configured pinA as output pin by sending out to direction attribute in sysfs and pinB as input by passing in. And I changed value of PinA to 1 and it is giving 1 as output (I tested using LED). But when I read the value of PinB it is giving 0 only, even I pass 0 to value of pinA. what may be the reason ?
Thank you :)
As I understood, the steps you followed:
echo 7 > /sys/kernel/debug/omap_mux/gpmc_ad6
echo 38 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio38/direction
cat /sys/class/gpio/gpio38/value
I also did the same mistake and it took me hours, but the answer was simple: The first line starting with "echo 7" is the problem. Look at the muxing bits:
Bit 5: 1 - Input, 0 - Output
Bit 4: 1 - Pull up, 0 - Pull down
Bit 3: 1 - Pull disabled, 0 - Pull enabled
Bit 2 \
Bit 1 |- Mode
Bit 0 /
You were entering echo 7 which is --> 0 0 0111 and it means: bit 0,1 and 2 is 1, so the mode is set. No problem. However you just forgot to set whether it's an input or output. And it should be like this:
echo 0x27 > /sys/kernel/debug/omap_mux/gpmc_ad6
your bits are now: 1 0 0111 binary which is 0x27 (hex).
When you write "cat /sys/class/gpio/gpio38/value" while giving input, you can see a wonderful 1 :) I’m sure you will be very happy as much as I was :)
Also, one more thing, you are right for Analog input about 1.8V, but GPIO operates with 3.3v.
Several possible causes:
1) Did you set the IO direction of the input pin?
eg. echo "in" > /sys/class/gpio/gpioN/direction
2) (less likely) Is the GPIO pin you're using as an input multiplexed as a GPIO line and in the right direction? Most of the GPIO pins on the OMAP SoCs are multi-function. You're kernel might have set it for an alternate function.
You can check it with:
cat /sys/kernel/debug/omap_mux/board/core
Which dumps the configurations of all IO pins. The output looks like this:
OMAP4_MUX(CSI22_DY1, OMAP_PIN_INPUT | OMAP_MUX_MODE0),
/* gpio_81 */
OMAP4_MUX(CAM_SHUTTER, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3),
OMAP4_MUX(CAM_STROBE, OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
/* gpio_83 */
In this case, CAM_SHUTTER is set an output, and routed as to the GPIO module (OMAP_MUX_MODE3)
[Caveat: this is from my OMAP4 board - without having the OMAP3 data sheet to hand - there will be a fair amount of similarity]
You can't change this through sysfs - instead you'll need to modify either your kernel (or possibly boot-loader if the kernel uses the configuration it set up).
In the board-file for your system - which I think in your case will be in <linux_source_root>/arch/arm/mach-omap2/board-omap3beagle.c - you'll find a initialiser for the MUX table. You will need the board's schematics, the kernel source tree and the SoC data sheet to get between the primary function name of the pin (in my example above CAM_SHUTTER) and a GPIO number.
3) I was a bit confused by even I pass 0 to value of pinA - I wonder whether you meant that? This does however point to another thing to watch for - there is the programmable pull-up or -down on each IO pin. These are set with the MUX settings. There may conceivably be an external one as well - again you'll need the schematics to be sure.
Yes. The internal pull up and down is configured in the same register as the mux-mode - so it might be that you can configure this in the same way you're setting the mux-mode. Get the AM335x TRM (for OMAP4 the chapter is called Control Module).
In terns of the kernel, look in <linux_source_root>/arch/arm/mach-omap2/mux.h where a bunch of macros are defined
As an example for use I have in my board file:
/* PIC -> OMAP4 interrupt line 2 - GPIO81 */
OMAP4_MUX(CAM_SHUTTER, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
and
OMAP4_MUX(GPMC_AD11, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
From memory you get a choice of either a pull-up or pull-down but can't select neither.

Resources