Web developer going into hardware so please, be gentle.
Problem: I'm currently trying to use the BlueFruit LE breakout board and an Arduino Micro, however the pinouts are different as the Micro has dedicated SPI pins whereas the UNO has SCK, MISO and MOSI doing double duty on pins 13, 12 and 11.
Question: Where in the Arduino IDE or the sample code I'm using can I change the requested pinouts?
Code:
echoDemo example sketch from Adafruit (truncated for brevity):
#include <SPI.h>
#include "Adafruit_BLE_UART.h"
// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2 // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9
As above states, the 'UNO & compatible...' are looking for the correct pins on said board.
I've done a search for the pins by name (CLK, etc) in the two #include files but haven't found their reference.
The result should be the following output in the Arduino IDE Console:
Adafruit Bluefruit Low Energy nRF8001 Print echo demo
* Advertising started
The second line should be returned from the BlueFruit LE board to the Micro and output to console.
My result is only the first line is output.
Understandably there are diagrams on the Arduino site where they detail the SPI pins and they're labelled clearly on the Micro (image attached). What I'm looking for is how/where to remap these pins to the Micro's pinout.
Any help, references or files to dig into would be a massive help.
•• Update
Thanks to the answers below, we're one step closer.
The following changes were made to the pinout in the sketch:
#include <SPI.h>
#include "Adafruit_BLE_UART.h"
// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ SS
#define ADAFRUITBLE_RDY 2 // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 3
And the following is the modified ble_system.h:
#ifndef BLE_SYSTEM_H_
#define BLE_SYSTEM_H
/*
#define HAL_IO_RADIO_CSN SS
#define HAL_IO_RADIO_REQN SS
#define HAL_IO_RADIO_RDY 3
#define HAL_IO_RADIO_SCK SCK
#define HAL_IO_RADIO_MOSI MOSI
#define HAL_IO_RADIO_MISO MISO
#define HAL_IO_RADIO_RESET 9
#define HAL_IO_RADIO_ACTIVE 8
//#define HAL_IO_LED0 2
//#define HAL_IO_LED1 6
*/
New Result:
• Same output in the console for Line 1 "Adafruit Bluefruit Low Energy nRF8001 Print echo demo".
• Typing "getState()" in console and hitting enter gives a massive parallel string of characters which crashes Arduino IDE
This looks like the BTLE breakout board may actually be working properly, but the data incoming to the Micro isn't being parsed properly.
Check out this Adafruit github page for their Bluetooth Low Energy Breakout board.
You don't need to worry about remapping the pins. Code that uses SPI will access it via the SPI peripheral in the MCU, which already knows the "correct" pins to use. So as long as the software uses the built-in SPI peripheral and the hardware connects to the SPI pins there is no need to change either.
Related
I am trying to setup a Half Duplex RS-485 communication using libmodbus on a Raspberry Pi running Raspian Buster, with a FTDI USB to Serial adapter. My FTDI adapter shows as ttyUSB0 when I run ls /dev/.
I tried the following sample code:
#include <modbus.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(void) {
modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'N', 8, 1);
if (ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
return 0;
}
if (modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485) == -1) {
fprintf(stderr, "Error setting the serial port as RS-485\n");
fprintf(stderr, "errno: %d\n (EBADF == 9)", errno);
modbus_free(ctx);
return 0;
}
}
Compiled with gcc test1.c -I/usr/include/modbus -lmodbus.
And I get errno as 9, or EBADF, even if I run this code with sudo.
There is a very easy solution to your problem: just don't set MODBUS_RTU_RS485, quite likely you don't need it.
This mode is actually a workaround for devices without automatic (hardware) direction control. As you know, Modbus RTU works over a half-duplex RS485 link (only one device is allowed to talk while all others must be listening only), and hence requires an additional (to RX and TX) signal to control what device is writing to the bus at all times (direction control).
So you would only need to set MODBUS_RTU_RS485 if your device lacks this feature, which is nowadays quite unlikely or if you are building your own transceiver. Most devices based on the FTDI chip, in particular, should have this feature since the chip itself has a TXDEN (transmit enable) pin. See here for more details and a trick to expose the TXDEN signal to a non-default pin.
It is when you don't have this feature (one frequent scenario is when you want to use the embedded UART on your Rpi for Modbus over RS485, implementing your own transceiver) that you need a software (or hardware) workaround. And that's where MODBUS_RTU_RS485 should come handy, repurposing the RTS flow control signal. Unfortunately, most serial drivers (including ftdi_sio, the one you are probably using) don't support this mode (refer again to the link above).
Luckily, there are workarounds to the workaround: see here for a complete discussion. You can also take a look at this answer where I explained how to set up libmodbus with support for toggling the direction on the bus using a GPIO pin on a Rpi (also applicable to most SBCs, I've used this method successfully with a Pocket Chip computer, for instance).
You can find more background on this issue elsewhere: here and here.
I am developing a 32 bit, protected mode hobby operating system. At the moment, I am looking to add simple sound support. To do this, I'm looking to use the sound blaster 16 and use the direct mode to write to the DAC (I want to avoid DMA at all costs). However, when I output a simple square wave to the DAC (using command 0x10), no sound is output from my computer's speakers. I'm looking for a solution to this problem.
I am trying to use the following algorithm to produce sound:
1. Reset DSP
2. Enable the speakers
3. Write 0x10 to 0x22C (direct mode DAC write command)
4. Write 0x00 to 0x22C (To set the speaker to low)
5. Write 0x10 to 0x22C
6. Write 0xFF to 0x22C (To set the speaker to high)
7. Jump back to step 4 and repeat.
Here is my code:
#define DSP_RESET 0x226
#define DSP_READ 0x22A
#define DSP_WRITE 0x22C
#define DSP_READ_STATUS 0x22E
#define DSP_INT_ACK 0x22F
#define REG_ADDR 0x224
#define REG_DATA 0x225
#define DIRECT_DAC 0x10
#define ENABLE_SPEAKER 0xD1
void dsp_reset(){
uint32_t buf[4];
*buf = 128;
rtc_write(0, buf, 4);
outb(1, DSP_RESET);
rtc_read(0, 0, NULL, 0);
outb(0, DSP_RESET);
if(inb(DSP_READ) != 0xAA){
print_term((uint8_t *)"Could not init sb16\n", 20);
}
return;
}
void play_simple_sound(){
dsp_reset();
while(inb(DSP_WRITE));
print_term((uint8_t *)"Enabling speaker\n", 18);
outb(0xD1, DSP_WRITE);
while(inb(DSP_WRITE));
print_term((uint8_t *)"Playing sound\n", 14);
outb(0xF0, DSP_WRITE);
while(1){
while(inb(DSP_WRITE));
outb(0x10, DSP_WRITE);
outb(0x00, DSP_WRITE);
rtc_read(0, 0, NULL, 0);
while(inb(DSP_WRITE));
outb(0x10, DSP_WRITE);
outb(0xFF, DSP_WRITE);
rtc_read(0, 0, NULL, 0);
}
return;
}
rtc_write sets the rtc frequency to a couple hundred hertz, and rct_read makes the program wait on the rtc (both these programs work correctly). The dsp_reset also works correctly, because when reading the output from the DSP, 0xAA is returned (which shows that a soundblaster 16 exists).
At the moment I am using windows 10 64 bit to run Qemu which emulates the operating system. I am running qemu with the "-soundhw all" option set. I am unsure whether I am unable to hear sound because of the code I have written or if there is something wrong with Qemu. My question is, what could the issue possibly be, and what are the steps I can take to fix this? Also, documentation and tutorials related to the sb 16 would be appreciated.
Under Qemu emulation, direct DAC is not possible using soundblaster 16. Direct ADC is not allowed either. Check the source code found here, look at the commands supported beginning on line 390:
https://github.com/qemu/qemu/blob/master/hw/audio/sb16.c
It looks like in order to output sound using the sound blaster card, you must use DMA. Going further, it looks like SB16 emulation on Qemu is pretty lacking. A good list of commands the real SB16 supports can be found here: http://the.earth.li/~tfm/oldpage/sb_dsp.html . Comparing these commands with what Qemu supports, only a small fraction are emulated.
Edit 2: Looking into other emulators, Bochs does not support sb16 (see line 858: http://bochs.sourceforge.net/cgi-bin/lxr/source/iodev/sound/sb16.cc), but DOSBox has very impressive SB16 support, and does support direct DAC, but still doesn't support microphone direct ADC (see line 1611: http://dosbox-x.com/doxygen/html/sblaster_8cpp_source.html)
Can anyone tell me why the characters are not getting printed properly in the serial monitor of Arduino? I am pasting the arduino code.
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,11,5,4,3,2);
int bluetoothTx = 15;
int bluetoothRx = 14;
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
int incomingByte;
void setup() {
pinMode(53, OUTPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
delay(320); // IMPORTANT DELAY! (Minimum ~276ms)
bluetooth.print("$$$"); // Enter command mode
delay(15); // IMPORTANT DELAY! (Minimum ~10ms)
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
bluetooth.begin(9600); // Start bluetooth serial at 9600
lcd.print("done setup");
}
void loop()
{
lcd.clear();
Serial.print("in loop");
//Read from bluetooth and write to usb serial
if(bluetooth.available()) {
Serial.print("BT here");
char toSend = (char)bluetooth.read();
Serial.print(toSend);
lcd.print(toSend);
delay(3000);
}delay(3000);
}
Can anyone take a look into it. It does not print the character that I provide instead it prints something else like 'y' with 2 dots on top etc. Tried almost all the available solution.
Your issues could be one of a couple things. First and easiest to check is COMMON GROUND. Did you connect just the RX and TX pins or also the GND (ground) pin? Make sure that the ground from the BT mate is connected to the Arduino ground.
If you have done that, then your issue is with the baud rate. I'm pretty sure that SoftwareSerial can't read at baud rates beyond 57600. Arduino.cc docs say it can read at 115200, but other places say it will only write up to 115200.
To test this, you will either need to change the settings for this on the Bluetooth Mate or use a Mega or Leonardo which will have a hardware serial port (other than the one used for USB) which you should be able to configure for 115200.
If you try it with hardware serial either on a Mega or just using an FTDI or something and the messages still look garbled then perhaps the bluetooth mate is not actually configured to talk at 115200 as it claims. Trying reading the docs or testing with other baud rates.
Check whether error is present due to one of the following reasons:-
1) You haven't given any command to exit from the data mode. After setting the baudrate to 9600, you are directly switching to loop. You haven't given the command to exit the command mode.
2) I too had the same problem when I was using RN171 Wi-Fi module. The cause of the problem in my case was because I was sending data to Wi-Fi module in integer format instead of uint_8. While reading from the Wi-Fi module serially with arduino mega, I was reading it in the format of characters.
You have to remember that int is actually signed 16 bit integer. So while sending data to your Bluetooth module you have to send it as uint_8 or ASCII values of the characters that you want to send. You should also read it in the same format as you sent it.
3) If these are not the error then as calumb said, there can be error in setting the bluetooth module in command mode. You haven't checked for reply from bluetooth module whether it is really in command mode or not. You must read an CMD reply from bluetooth module and at the end of every command a reply of ack to conform that its really done what you want it to do.
This may be because of Bluetooth parsing data simultaneously. when sending two different data at the same time this may happens. try to control your data flow.
i'm doing a project in which i need to handle an interrupt in Linux.
the board i'm using is an ARM9Board based on the s3c6410 MCU by Samsung (arm 11 processor) and it has the following I/O interface :
as the image shows i have EINTx pins for external interrupts and GPxx pins as GPIO pins and i don't mind using any of them but i don't have their numbers !
For EINTx pins :
when i call
int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
unsigned long flags, const char *device);
i need the interrupt number to pass it as the first paramter of the function , so how can i get the irq number for example the EINT16 pin ?
For GPxx pins :
the same story as i need the GPIO pin nuumber to pass it to those functions
int gpio_request(unsigned gpio, const char *label);
int gpio_direction_input(unsigned gpio);
int gpio_to_irq(unsigned gpio);
i.e how do i know the GPIO number for the GPP8 pin ?
i searched the board documents and datasheet but it doesn't contain anything about how to get those numbers , any idea or help on where to look ?
The Embedded Linux you are using should have a GPIO driver that has #define statements for the GPIO pins. You can then get the IRQ number of the specific GPIO using something like:
irq_num = gpio_to_irq(S3C64XX_GPP(8));
The Linux GPIO lib support for that particular chip is available in the following file:
linux/arch/arm/mach-s3c6400/include/mach/gpio.h
There you will find all the #define statements for the various GPIO.
See the section on GPIO Conventions in their documentation:
http://www.kernel.org/doc/Documentation/gpio/gpio.txt
I was doing some work on the GPIO pin as well but it's on a different board, AM335x. Just to let you know, there's quite few of way to do it. One of the method we are using is using memory board to access (write or read) the GPIO pin.
This is a really good article to help me to get things working. Register access to the GPIOs of the Beaglebone via memory mapping
I'm writing a RS485 driver for an ARM AT91SAM9260 board on Linux.
When I initialise the UART, the RTS signal line gets high (1). I guess this would and should be the standard behaviour in RS232 operation mode. In RS485 mode however this is not wanted.
I'm using the standard functions provided by the arm-arch section to initialise the UART. Therefore the significant steps are:
at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
//consisting of:
// >> configure/mux the pins
at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD */
at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD */
if (pins & ATMEL_UART_RTS)
at91_set_B_periph(AT91_PIN_PC8, 0); /* RTS */
if (pins & ATMEL_UART_CTS)
at91_set_B_periph(AT91_PIN_PC10, 0); /* CTS */
// >> associate the clock
axm_clock_associate("usart3_clk", &pdev->dev, "usart");
// >> et voilà
As you can see with
at91_set_B_periph(AT91_PIN_PC8, 0);
the pull-up on the RTS pin isn't activated.
Why does the UART set the RTS high?
Just because this would be the standard
behaviour in RS232 mode?
Wouldn't it be a better standard for
the UART to keep silent till the
operation mode is explicitly set?
A high RTS signal after initialisation seems to be the standard behaviour on many platforms. It manly depends which serial operation mode the start-up routines anticipates for the interface.
To prevent RTS-high on a ATMEL AT91SAM9260 board running Linux, you have to put the UART into the right mode BEFORE muxing at91_set_X_periph() the Pins and register the device.
Since Linux Kernel Version 2.6.35, the ATMEL serial driver supports the RS485 mode. In this driver the UART is properly configured before setting the Pins (GPIO) to there role.
For my embedded device which is running an older Linux version, I solved the problem with the following line of codes:
/* write control flags */
control |= ATMEL_US_RTSEN;
mode |= ATMEL_US_USMODE_RS485;
UART_PUT(uartbaseaddr, ATMEL_US_CR, control);
UART_PUT(uartbaseaddr, ATMEL_US_MR,mode);
Now the Pins can be muxed the their role
at91_set_X_periph(RTS_PIN, 0);