Arduino SoftwareSerial Rx/Tx pin order error? - serial-port

I'm writing code to run on an ATtiny being programmed by an Arduino as ISP. The ATtiny is to send AT commands over serial link to an RN42 Bluetooth module.
Since the ATtiny has no UART I'm using SoftwareSerial on pins 0 and 1. It seemed logical to put Tx on the "Data Out"/MISO pin and Rx on the "Data In"/MOSI pin. The documentation says to declare this like SoftwareSerial mySerial(Rx, Tx); but I found it only works if you declare it the other way round like SoftwareSerial mySerial(Tx, Rx);
I've taken a screenshot of my code and the pinout, I feel like I'm missing something but when I do it like this it works and makes the Bluetooth module enter command mode. Is the documentation the wrong way round?
Code and Pinout

I realised the error of my ways, I was unnecessarily setting the pinMode of the Rx and Tx pins. This threw me off as I thought setting the Rx pin to OUTPUT wouldn't work when actually it does, so I was outputting data on my Rx line and receiving it on the Tx line! The answer is to not assign direction and just let SoftwareSerial handle the pins. Pass the parameters in the order (Rx, Tx).
Here is my cleaner code that is working much better:
#include <SoftwareSerial.h>
const int Rx = 0; // pin 5 on ATtiny - DI/MOSI
const int Tx = 1; // pin 6 on ATtiny - DO/MISO
const int ButtonIn = 2;
const int OK_LED = 4;
int buttonState = 0;
SoftwareSerial serialBT(Rx, Tx);
void setup()
{
pinMode(ButtonIn, INPUT);
pinMode(OK_LED, OUTPUT);
serialBT.begin(9600);
}
void loop()
{
buttonState = digitalRead(ButtonIn);
if (buttonState == 0)
{
serialBT.print("$"); // $$$ enters RN42 command mode
serialBT.print("$");
serialBT.print("$");
delay(3000);
serialBT.println("R,1");
digitalWrite(OK_LED, HIGH);
delay(5000);
digitalWrite(OK_LED, LOW);
}
}

Related

How to connect MAX30100 pulse sensor to a different i2c pins of ESP32 and read data?

I'm using a ESP32 30 pin board, MAX30100 pulse sensor for my project.
I can interface this sensor to ESP32's different i2c pins i.e. not default pins(21,22).
But I don't know how to read data from the MAX30100 if it connected to different pins - (Let's say 32, 33)
This is the program I used for default i2c pins to read data from MAX30100
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define BLYNK_PRINT Serial
#include <Blynk.h>
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#define REPORTING_PERIOD_MS 1000
char auth[] = "*******************"; // You should get Auth Token in the Blynk App.
// Connections : SCL PIN - D1 , SDA PIN - D2 , INT PIN - D0
PulseOximeter pox;
float BPM, SpO2;
uint32_t tsLastReport = 0;
void onBeatDetected()
{
Serial.println("Beat Detected!");
}
void setup()
{
Serial.begin(115200);
pinMode(19, OUTPUT);
Blynk.begin(auth,"************", "**********");
Serial.print("Initializing Pulse Oximeter..");
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
}
else
{
Serial.println("SUCCESS");
pox.setOnBeatDetectedCallback(onBeatDetected);
}
// The default current for the IR LED is 50mA and it could be changed by uncommenting the following line.
pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
}
void loop()
{
pox.update();
Blynk.run();
BPM = pox.getHeartRate();
SpO2 = pox.getSpO2();
if (millis() - tsLastReport > REPORTING_PERIOD_MS)
{
Serial.print("Heart rate:");
Serial.print(BPM);
Serial.print(" bpm / SpO2:");
Serial.print(SpO2);
Serial.println(" %");
Blynk.virtualWrite(V3, BPM);
Blynk.virtualWrite(V4, SpO2);
tsLastReport = millis();
}
}
How do I interface MAX30100 to other pins? What should be the instructions?
PulseOximeter pox;
What does this instruction mean?
You should change direction in library:
Link to library file in github
Line 29: change that for
Wire.begin(SDA_PIN, SCL_PIN);
Where SDA_PIN and SCL_PIN are defines of your own routing.
NOTE: if you change the library you will need always to use that pins for all of your developments so maybe is better if you import that library locally or even better if you change library so if you don't pass any pin at argument it default normally I2C pins but, if defined use the defined ones.

how can i count pulses using analog pin of arduino

The frequency of the pulses range from 1-10000 Hz and voltage ranges from 1-5 volt. I have tried the following code, its working for digital pins but not for analog.Do you guys have any solution for it.
int pin = A0;
volatile unsigned int pulse = 0;
void setup()
{
Serial.begin(9600);
pinMode(pin, INPUT_PULLUP);
attachInterrupt(0, count_pulse, RISING);
}
void loop()
{
pulse=0;
interrupts();
delay(100);
noInterrupts();
Serial.print("Pulses per second: ");
Serial.println(pulse);
}
void count_pulse()
{
pulse++;
}
Different Arduino boards (Mega, Uno, Nano etc) are different in terms of which pins work with interrupts. You need to read the documentation for your board, or much better, use #ifdef to adapt to any board:
#ifdef __AVR_ATmega32U4__ // Leonardo has different int mapping
#ifdef __SAM3X8E__ // Due processor has different timer setup
#ifdef __AVR_ATmega328P__
Check out the documentation on arduino.cc/reference.
In short if you are using the arduino uno you can only use the digital pin #2 and #3 for attachinterrupt() operation... https://youtu.be/srr0TTRPPKU

Having problems blinking an LED on Arduino using information sent over CAN-bus

I've been messing around with CAN-bus to try and learn the basics so I can use it in a future project. I have 2 arduinos with MCP2515 chips connected that I am sending messages between.
I have been able to wire up the chips and send messages between the arduinos just fine, but when I went to modify the code to blink an LED if the first byte is 0x00 or 0x01 it wont blink. I added print statements to check that it is entering the loop, and it is, using the serial monitor I can see it yeet and yote, but digital pin 3 remains at ~0V.
This is probably more an arduino question than a CAN-bus question but could somebody help me understand why my LED wont blink? The code is entering the loop so it should be processing the command, and I initialized the pin to be an output, but i'm still not getting any blinking.
As a note, the transmitting arduino is sending alternating packets of data, first a packet with 0X01 as the first data byte, then with 0x00 as the first data byte. These data packets are separated by 5000 ms.
I am currently using the CAN library available here https://github.com/autowp/arduino-mcp2515
Code for receiving arduino
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);
int LED_PIN = 3;
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(LED_PIN, OUTPUT);
mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
mcp2515.setNormalMode();
Serial.println("------- CAN Read ----------");
Serial.println("ID DLC DATA");
}
void loop() {
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
Serial.print(canMsg.can_id, HEX); // print ID
Serial.print(" ");
Serial.print(canMsg.can_dlc, HEX); // print DLC
Serial.print(" ");
if(canMsg.data[0] == 0x00){
digitalWrite(LED_PIN,HIGH);
Serial.print("YEET");
}
if(canMsg.data[0] == 0x01){
digitalWrite(LED_PIN,LOW);
Serial.print("YOTE");
}
for (int i = 0; i<canMsg.can_dlc; i++) { // print the data
Serial.print(canMsg.data[i],HEX);
Serial.print(" ");
}
Serial.println();
}
}
and the code for transmitting arduino for completeness
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
void setup() {
canMsg1.can_id = 0x0F6;
canMsg1.can_dlc = 8;
canMsg1.data[0] = 0x01;
canMsg1.data[1] = 0x87;
canMsg1.data[2] = 0x32;
canMsg1.data[3] = 0xFA;
canMsg1.data[4] = 0x26;
canMsg1.data[5] = 0x8E;
canMsg1.data[6] = 0xBE;
canMsg1.data[7] = 0x86;
canMsg2.can_id = 0x036;
canMsg2.can_dlc = 8;
canMsg2.data[0] = 0x00;
canMsg2.data[1] = 0x00;
canMsg2.data[2] = 0x00;
canMsg2.data[3] = 0x08;
canMsg2.data[4] = 0x01;
canMsg2.data[5] = 0x00;
canMsg2.data[6] = 0x00;
canMsg2.data[7] = 0xA0;
while (!Serial);
Serial.begin(115200);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
mcp2515.setNormalMode();
Serial.println("Example: Write to CAN");
}
void loop() {
mcp2515.sendMessage(&canMsg1);
delay(5000);
mcp2515.sendMessage(&canMsg2);
Serial.println("Messages sent");
delay(5000);
}
Sorry, i'm an idiot. I forgot that breadboard power lines are not connected all the way down the board. I connected the Arduino to the proper section of the breadboard to receive power and ground, but connected the LED to an unconnected ground pin.

NRF24L01 with ATTiny and Uno not connecting

I have an ATTiny85 connected to an NRF24L01+ module using this wiring diagram: diagram. The ATTiny85 periodically goes in and out of sleep to send some value to a receiver, an Arduino Uno. If the ATTiny is running off the Arduino power supply (3.3v), everything works correctly. When I run the ATTiny off of a separate CR2032 coin cell that delivers around 3v, the Arduino never receives any data. I have a status LED hooked up to the ATTiny to ensure that the ATTiny is waking correctly, which it is. Here's the code for both:
EDIT:
Connecting it to an external 3.3v not from the Uno makes everything work - why wouldn't the coin cell's voltage work? I think everything is rated below 2.8v, the CR2032 minimum.
ATTiny Code
#include <avr/sleep.h>
#include <avr/interrupt.h>
// Routines to set and claer bits (used in the sleep code)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define CE_PIN 3
#define CSN_PIN 3 //Since we are using 3 pin configuration we will use same pin for both CE and CSN
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "SimpleNode";
unsigned long payload = 0;
void setup() {
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openWritingPipe(address); // Write to device address 'SimpleNode'
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(1000);
setup_watchdog(6);
}
volatile int watchdog_counter = 0;
ISR(WDT_vect) {
watchdog_counter++;
}
void loop()
{
sleep_mode(); //Go to sleep!
if(watchdog_counter >= 5)
{
digitalWrite(4, HIGH);
watchdog_counter = 0;
payload = 123456;
radio.write( &payload, sizeof(unsigned long) ); //Send data to 'Receiver' ever second
delay(1000);
digitalWrite(4, LOW);
}
}
//Sleep ATTiny85
void system_sleep() {
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System actually sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
Receiver Code
#define CE_PIN 7
#define CSN_PIN 8
#include <SPI.h>
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "SimpleNode";
unsigned long payload = 0;
void setup() {
while (!Serial);
Serial.begin(115200);
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openReadingPipe(1, address); // Write to device address 'SimpleNode'
radio.startListening();
Serial.println("Did Setup");
}
void loop(void){
if (radio.available()) {
radio.read( &payload, sizeof(unsigned long) );
if(payload != 0){
Serial.print("Got Payload ");
Serial.println(payload);
}
}
}
Is the problem here that the ATTiny and Uno need to be turned on at the same time to establish a connection, or is it something to do with the battery, or something else entirely? Any help would be appreciated.
I'm experiencing the same problem when running Arduino Nano from a battery.
Nano has a 3.3V pin that I'm using for powering the NRF24L01+ module.
When the voltage from my battery-pack drops under 3.3V, the 3.3V pin voltage also drops. After few minutes, the RF module is not sending any messages.
I fixed the problem temporarily by routing the battery through a 12V step-up regulator that I bought earlier for a different project. These 12V then go to the "UN" pin on Nano which accepts 6-20V. This setup works nicely but is definitely not optimal.
Therefore I'm planning to use a 3.3V step-up regulator such as Pololu 3.3V Step-Up Voltage Regulator U1V11F3 which, according to the supplier, can efficiently generate 3.3V from input voltages as low as 0.5V.
I think this might be helpful to your project as well.

MicroSD reader causing RFID reader to fail

I have a sketch running a MFRC522 RFID reader which works fine but my aim is to log the card swipes on a microSD card.
The problem is that as soon as I add the SD card reader, whether it is initialised or not, the RFID reader stops working.
It seems to be a problem on the SPI bus. I have tried adding pull up resistors to the circuit and setting the chip select pins to HIGH before initialising either of the boards but nothing seems to work.
Here is my code:
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>
// RFID constants & objects
#define RFPin 10
#define resetPin 9
MFRC522 mfrc522(RFPin, resetPin);
// SD constants
#define SDPin 8
// Other global variables
String IDString;
byte IDList[4];
void setup() {
pinMode(2, OUTPUT);// For testing
// Set both chip select pins high
pinMode(SDPin, OUTPUT);
digitalWrite(SDPin, HIGH);
pinMode(RFPin, OUTPUT);
digitalWrite(RFPin, HIGH);
delay(10);
// Init serial bus
Serial.begin(9600);
// Wait for serial bus to open
while (!Serial);// Opens even when not USB connected
// Init SPI bus
SPI.begin();
// Initialise RFID board
mfrc522.PCD_Init();
delay(1000);// Just in case SPI is still busy
// Initialise SD card board
if (!SD.begin(SDPin)) {
// SD card board failed to initialise
Serial.println("SD failed");
return;
}
}
void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
for(int i = 0; i < 4; i++) {
digitalWrite(2, HIGH);
delay(100);
digitalWrite(2, LOW);
delay(100);
}
IDString = "";
// Get 4 byte ID
for (int i = 0; i < 4; i++) {
IDList[i] = mfrc522.uid.uidByte[i];
// Serial.print(IDList[i], HEX);
if(IDList[i] < 16) {
IDString += "0" + String(IDList[i], HEX) + "-";
} else {
IDString += String(IDList[i], HEX) + "-";
}
}
mfrc522.PICC_HaltA(); // Stop reading
IDString = IDString.substring(0, IDString.length() - 1);
Serial.println(IDString);
.
.
.
Rest of code
Everything initialised ok but Once in the main loop, the program never gets past the first statement: to check if an RFID card is present.
Can anybody help?
Could it be de to the fact that the RFDI board is 3.3V driven and the SD board is 5V driven (but has a 3.3V regulator)? Each has it's own separate power wire
EDIT #1:
When the MicroSD board is plugged in but not powered the RFID board works fine
I have also tried adding a subroutine to pull both chip select pins high at the beginning of every loop to no avail.
EDIT #2:
The SD board works in this sketch and I can get the card details from it.
EDIT #3:
The RFID card works again once I remove the MISO line from the SD board.
Obviously the SD module isn't releasing the MISO line...
It's not the most elegant solution but I have it working now by attaching an NPN transistor between the MISO output of the SD board and the MISO line to pin 12. It takes one further pin to block/unblock the MISO line to be used by the SD board but it works.
As I said this is not elegant and I would still be eager to hear a better solution.

Resources