I like to sample an analogue mic sample. The sampling should be synced with the I2S master clock. Since I like to do some DSP after, a block of samples should be processed while another block should is sampled.
My MCU is a DSPIC33CH128MP205.
So I tried to setup everything but I am still failing.Maybe someone can spot what I am doing wrong here or advise me.
I am using MPLAB with the MCC tool. Here the screenshots of the setup
ADC:
DMA:
PIN control:
Some init code:
uint16_t mic_in[64*2];
void DMA_Channel2_CallBack(void) {
if (DMA_IsOperationHalfComplete(DMA_CHANNEL_2)) {
}
if (DMA_IsOperationDone(DMA_CHANNEL_2)) {
}
}
void adc_init(void) {
// ADC1_IndividualChannelInterruptEnable(channel_AN8);
// channel 2 -> ADC channel 8 (RB3) + ADC trigger RB4 -> mic.mic_in
DMA_ChannelDisable(DMA_CHANNEL_2);
DMA_DestinationAddressSet(DMA_CHANNEL_2, (uint16_t) &mic_in[0]);
DMA_SourceAddressSet(DMA_CHANNEL_2, (uint16_t) &ADCBUF8);
DMA_TransferCountSet(DMA_CHANNEL_2, sizeof(mic_in)/sizeof(uint16_t));
DMA_ChannelEnable(DMA_CHANNEL_2);
//DMA_SoftwareTriggerEnable(DMA_CHANNEL_2);
// ADC1_SoftwareTriggerEnable();
ADC1_InterruptFlagClear();
ADC1_Enable();
//ADC1_SharedCorePowerEnable();
}
Related
I want to reproduce a .wav file on my Arduino Uno via an SD card while at the same time using an LCD display (Nokia 5110). I'm having trouble trying to make the double SPIs work and since I'm not really familiar with the libraries that I used I decided to ask for help
The problem is that once the program execute SD.begin() the display stops working and the SPI communication is working only on the SD.
In this setup that I'm showing I will initialize the SD in the setup() and in the loop using a button I'm supposed to write stuff on the display:
//Libraries
#include <U8x8lib.h>
#include <SPI.h>
#include "SD.h"
#include "TMRpcm.h"
//Display (pin 13, pin 11, pin A1, pin 12, pin A0 )
U8X8_PCD8544_84X48_4W_SW_SPI lcd(LCD_CLK, LCD_DIN, LCD_CE, LCD_DC, LCD_RST);
//Speaker
TMRpcm music;
void setup() {
//Serial port -> Open
Serial.begin(9600);
while (!Serial) {}
//LCD
display_setup();
//SD and Speaker
sdAndSpeaker_setup();
}
void loop() {
topButton.poll();
if (topButton.buttonClicked) {
display_something();
}
}
Ignore the function related to the button, I removed most of its code to avoid cluttering the page.
Here's when the problem occurs:
void sdAndSpeaker_setup() {
music.speakerPin = 10;
// (pin 4)
if (!SD.begin(SD_CS)) {
Serial.println("SD fail");
Serial.flush();
abort();
}
music.setVolume(4);
music.play("Daybreak.wav");
music.quality(2);
}
I know that by changing the pins of display to other value (rather than 11, 12 and 13) the problems is solved but most of the pins in my board are already used and I don't have this luxury... I think this has something to do with the U8x8.h and SD.h library but I don't have the skills to tweak those.
If anyone has a suggestion I'll appreciate!
Thanks!
EDIT:
Thanks to Juraj for the clarification, here's my new changes for the corrected constructor:
U8X8_PCD8544_84X48_4W_HW_SPI lcd(LCD_CE, LCD_DC, LCD_RST);
And for the setup_display()
void display_setup() {
lcd.begin();
pinMode(LCD_LIGHT, OUTPUT);
digitalWrite(LCD_LIGHT, HIGH);
lcd.setFont(u8x8_font_chroma48medium8_r);
lcd.drawString(1,2, "Hello!");
}
Unfortunately it still doesn't work...
The constructor
U8X8_PCD8544_84X48_4W_SW_SPI(uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE)
creates a 'driver' which uses software SPI. But you supply pins of hardware SPI as parameters. Hardware SPI is used by the SD library over the SPI library to access the SD card, so hardware SPI conflicts with the software SPI of the display library.
There is a
U8X8_PCD8544_84X48_4W_HW_SPI(uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE)
constructor which uses the hardware SPI over the SPI library. The SPI library 'knows' the pin numbers of the SPI pins. (SPI library is part of the boards package. It can't be installed separately.)
If you want to use the software SPI, use free pins. The hardware SPI uses pins 11, 12, 13 on Uno.
Recently I have a project to use a Linux host to communicate with an ADC device(SPI communication). I use my knowledge to write a device driver for it.
The goal of this driver is to read ADC data and transfer them to userspace. My idea is when the Linux host gets the DRDY signal(data ready signal, the signal means the data of ADC can be read) from ADC, an interrupt will be triggered, and the SPI read API of the driver will read data from the SPI bus. the data will fill into a buffer, when the buffer is full, the driver sends a SIGNAL to the userspace program, and the data in the buffer will be read by the userspace.
Although this idea may not be a perfect plan to realize my goal, I finish the code above. Unfortunately, I face a question that makes my goal failed.
The SPI transfer API of the Linux host should be put into the bottom half of the interrupt(due to the sleep mechanic of SPI API), that is to say, if the sample rate of AD is too fast, the bottom half of the interrupt may read a delayed data of ADC, when I use 4kHz sample rate, there are 7997 interrupts, but only 7907 data has been read. When I use the 250Hz sample rate, my idea is OK. But, I must use at least 4ksps.
I do not know whether you have some experience with this kind of problem, or maybe my idea is not suited for the high-speed ADC, I hope you can give me some suggestions, thanks a lot.
Here is some core code of my idea. The SPI transfer function:
int get_ad_data(struct spi_device *ad_spi_dev)
{
int ret = -1;
gpio_set_value(ADS1299_CS_PIN, 0);
if( ad_spi_dev )
{
struct spi_transfer tr =
{
.tx_buf = &send_data,
.rx_buf = &get_data,
.len = 27,
};
ret = spi_sync_transfer(ad_spi_dev, &tr, 1);
}
printk("%02x, %02x, %02x\r\n",get_data[6],get_data[7],get_data[8]);
gpio_set_value(ADS1299_CS_PIN, 1);
return ret;
}
The interrupt handler:
static irqreturn_t drdy_handler(int irq, void *dev_id)
{
struct ads1299_dev *dev = dev_id;
schedule_work(&dev->drdy_irq.work_drdy);
return IRQ_HANDLED;
}
static void drdy_work(struct work_struct *work)
{
int ret;
ret = get_ad_data(ads1299_spi_dev);
}
I've been tinkering with the MFRC-522 (RC-522) RFID module for a project.
I'm testing authentication using an old key to check if the RFID's key A for a sector (in my case, Sector 2) is different from the original, if it was, then I would continue, if not I would like to "register" the card by changing the key.
I was caught at the beginning on checking different keys authentication, if I tested a working key and then an incorrect key, it works as expected, but if I test with the incorrect key first, it doesn't allow even the correct key to authenticate.
If I ran the code below everything in serial is
PCD_Authenticate() failed NEW(read): Timeout in communication.
PCD_Authenticate() failed OLD(read): Timeout in communication.
repeatedly but if I flipped old() and neww() I get
OLD WORKS
PCD_Authenticate() failed NEW(read): Timeout in communication.
Why does it work as such?
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 22 // Configurable, see typical pin layout above
#define SS_PIN 21 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key old_key = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
MFRC522::MIFARE_Key new_key = {0x23,0x54,0x64,0x3a,0x32,0x66};
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
void loop() {
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
neww();
old();
}
void old(){
//authentication of the desired block for access
byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &old_key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed OLD(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status));
return;
}else {Serial.println("OLD WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
void neww() {
//authentication of the desired block for access
byte status_new = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &new_key, &(mfrc522.uid));
if (status_new != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed NEW(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status_new));
return;
} else {Serial.println("NEW WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
So, after reading the datasheet extra hard I came to the conclusion that the state of the card was not ready for the next read, so I came with a fire-all-guns solution that helped my case, The Serial prints are for debugging so if using the code feel free to comment them out.
bool reselect_Card() {
//-------------------------------------------------------
// Can also be used to see if card still available,
// true means it is false means card isnt there anymore
//-------------------------------------------------------
byte s;
byte req_buff[2];
byte req_buff_size=2;
mfrc522.PCD_StopCrypto1();
s = mfrc522.PICC_HaltA();
Serial.print("Halt Status: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
delay(100);
s = mfrc522.PICC_WakeupA(req_buff,&req_buff_size);
Serial.print("Request: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
Serial.print("ATQA : ");
Serial.println(dump_byte_array_to_string(req_buff,req_buff_size));
delay(100);
s = mfrc522.PICC_Select( &(mfrc522.uid),0);
Serial.print("Selected : ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
if( mfrc522.GetStatusCodeName((MFRC522::StatusCode)s) == F("Timeout in communication.") ) { return false;}
return true;
}
I am able to connect a Raspberry Pi 4 an and Arduino Nano BLE through bluepy for Rpi4 and ArduinoBLE.h for Arduino Nano BLE. Unfortunately when I try to write from Rpi4 to Arduino Nano BLE, I'm not seeing the expected output for Read and Write. I don't see any perfect example for Arduino Nano BLE since it is recently released hardware with built-in BLE. It would be very helpful if anyone could help me achieve communication between them. Thanks in advance. Below is my code for Raspberry Pi.
import bluepy.btle as btle
p = btle.Peripheral("de:fc:54:87:b0:04")
services=p.getServices()
s = p.getServiceByUUID(list(services)[2].uuid)
c = s.getCharacteristics()[0]
c.write(bytes("2", "utf-8"))
p.disconnect()
And I'm using the Arduino built-in example from the Arduino Nano BLE Library.
#include <ArduinoBLE.h>
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
const int ledPin = LED_BUILTIN; // pin to use for the LED
void setup() {
Serial.begin(9600);
while (!Serial);
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
//prints the centrals MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println(F("LED off"));
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
I figured out myself, it was the value in the write which was going wrong all this time. Below is the right one. I hope now you can find this as a perfect solution to connect raspberry Pi 4 and Arduino Nano BLE wirelessly Via Bluetooth.
c.write(bytes("0001".encode())
I am trying out Arduino Uno + HC-05 using this library. I don't think it is working properly. This is the Serial Monitor's output of the example "echo":
findBaud
Trying 4800... x
Trying 9600... x
Trying 19200... x
Trying 38400... x
Trying 57600... x
Trying 115200... x
No connection
No Connection, waiting...OK
None of the Communication speed works, but I manage to connect my Android phone (w/ Bluetooth Terminal) to the HC-05, which is why you see "OK" at the end of the output. But it is not able to echo my input from the Bluetooth Terminal.
The Arduino code:
#include <Arduino.h>
#include "HC05.h"
#include <SoftwareSerial.h>
HC05 btSerial = HC05(A2, A5, A3, A4); // cmd, state, rx, tx
void setup()
{
DEBUG_BEGIN(57600);
btSerial.findBaud();
}
void loop()
{
btSerial.println("Echo Server- type something");
while (btSerial.connected())
{
if (btSerial.available())
{
btSerial.write(btSerial.read());
}
}
}
How I connect the HC-05 to Arduino:
I just follow the instruction(5V and GND; State, Rx and Tx to A5, A3 and A4 respectively) , except I don't have pin "cmd", but I do have pin "CFG", so I just assume that should be cmd and connect it to A2
(I know I should comment instead of writting an answer, but I need 50 reputation)
Same here.
I tried with and without the lib and with different pins. I also tried an arduino micro and uno.
Always the same: the module's LED blink (when I send data trough RX/TX it seems) but I can't have any answer (neither when switching to command mode with "$$$" and neither with AT commands with KEY pin - on my module it is named EN, maybe for enable, I assume it is the same)
EDIT:
I should have RTFM. Especially this.
Here are my findings :
The bluetooth module is called HC-05 and the whole board I have is ZS-040.
The EN pin is used to switch off the module, if set to LOW
The small button switch can be pushed to enter command mode (I don't have a KEY pin)
Speed is 9600 bauds by default and stay the same when entering command mode
To debug your connection you can use the Android app called BlueSerial
For the record, here is my code :
#include <SoftwareSerial.h>
#define HC05_STATE 5
#define HC05_RXD_ARDUINO_TXD 4
#define HC05_TXD_ARDUINO_RXD 3
#define HC05_EN 2
SoftwareSerial BTSerial(HC05_TXD_ARDUINO_RXD, HC05_RXD_ARDUINO_TXD); // RX | TX
void setup(void)
{
pinMode(HC05_EN, OUTPUT);
digitalWrite(HC05_EN, HIGH); // just to be sure to enable the module, if not plugged it still works
Serial.begin(9600);
BTSerial.begin(9600); // default speed
Serial.println("Ready");
}
void loop(void)
{
if (BTSerial.available())
{
Serial.print("< ");
while (BTSerial.available())
Serial.write(BTSerial.read());
Serial.print("\n");
}
if (Serial.available())
{
Serial.print("> ");
while (Serial.available())
{
char c = Serial.read();
BTSerial.write(c);
Serial.write(c);
}
Serial.print("\n");
}
}