I am currently developing a driver for the RM3100 magnetometer but am running into issues reading and writing to the registers. Currently, I am trying to read the STATUS register to determine if the sensor is collecting data; however, I get a zero every time. Is there an issue with the way that I am trying to access the registers? Or is there some error in my code?
C++ file:
#include "Arduino.h"
#include "QRM3100.h"
#include <Wire.h>
#include <math.h>
#define CALIBRATION_TIMEOUT 5000 //timeout in milliseconds
#define DEG_PER_RAD (180.0/3.14159265358979)
QRM3100::QRM3100() {
//Just some random initial values
}
void QRM3100::initialize() {
Wire.begin();
}
uint8_t QRM3100::readRegister(uint8_t address){
uint8_t output;
Wire.beginTransmission(QRM3100_I2C_ADDRESS);
Wire.write(address);
Wire.endTransmission();
delayMicroseconds(20);
Wire.requestFrom(QRM3100_I2C_ADDRESS, 1);
while(Wire.available())
{
output = Wire.read();
}
return output;
}
void QRM3100::writeRegister(uint8_t address, uint8_t value){
Wire.beginTransmission(QRM3100_I2C_ADDRESS);
Wire.write(address);
Wire.write(value);
Wire.endTransmission();
}
bool QRM3100::dataReady() {
return ((readRegister(QRM3100_STATUS_REG) & 0x80) >> 7);
}
void QRM3100::start() {
exitStandby();
}
void QRM3100::exitStandby(){
writeRegister(QRM3100_CMM, 0b011100001);
}
Header file:
#ifndef QRM3100_h
#define QRM3100_h
#include "Arduino.h"
#include "Wire.h"
#define QRM3100_CMM 0x01 //initiates continuous measurement mode
#define QRM3100_STATUS_REG 0x34 //status of DRDY
#define QRM3100_I2C_ADDRESS 0x21
#define QRM3100_POLL 0x00 //poll
class QRM3100
{
public:
QRM3100();
void initialize();
uint8_t readRegister(uint8_t address);
void writeRegister(uint8_t address, uint8_t value);
bool dataReady();
void start();
void exitStandby();
bool error;
};
#endif
Arduino file:
#include <C:\Users\daehy\OneDrive\Documents\Arduino\libraries\src\QRM3100X.h>
#include <C:\Users\daehy\OneDrive\Documents\Arduino\libraries\src\QRM3100X.cpp>
QRM3100 mag = QRM3100();
void setup() {
Serial.begin(9600);
mag.initialize();
mag.start();
}
void loop() {
Serial.println( mag.dataReady());
}
It seems you haven't set the CMM register first. The default value may not be correct for continuous mode. Try setting the CMM register (0x01) to the following:
(CMM_ALL_AXIS_ON | DRDY_WHEN_ALL_AXIS_MEASURED | CM_START)
( 0x70 | 0x08 | 0x01 )
that should give you a final binary value of,
|LDM|CMZ|CMY|CMX|DRDM1|DRDM0|ALARM|START|
| 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
or 0x79 in hex
Related
I am trying to interface an LCD using I2C but can't quite understand how to do it.
I found this example
Here's the code:
i2c.h:
/* File: I2C_LCD.h */
#define _XTAL_FREQ 16000000
#define I2C_BaudRate 100000
#define SCL_D TRISC3
#define SDA_D TRISC4
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define LCD_FIRST_ROW 0x80
#define LCD_SECOND_ROW 0xC0
#define LCD_THIRD_ROW 0x94
#define LCD_FOURTH_ROW 0xD4
#define LCD_CLEAR 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_ENTRY_MODE_SET 0x04
#define LCD_CURSOR_OFF 0x0C
#define LCD_UNDERLINE_ON 0x0E
#define LCD_BLINK_CURSOR_ON 0x0F
#define LCD_MOVE_CURSOR_LEFT 0x10
#define LCD_MOVE_CURSOR_RIGHT 0x14
#define LCD_TURN_ON 0x0C
#define LCD_TURN_OFF 0x08
#define LCD_SHIFT_LEFT 0x18
#define LCD_SHIFT_RIGHT 0x1E
#define LCD_TYPE 2 // 0 -> 5x7 | 1 -> 5x10 | 2 -> 2 lines
//-----------[ Functions' Prototypes ]--------------
//---[ I2C Routines ]---
void I2C__Init();
void I2C__Wait();
void I2C__Start();
void I2C__RepeatedStart();
void I2C__Stop();
void I2C_ACK();
void I2C_NACK();
unsigned char I2C__Write(unsigned char data);
unsigned char I2C_Read_Byte(void);
//---[ LCD Routines ]---
void LCD_Init(unsigned char I2C_Add);
void IO_Expander_Write(unsigned char Data);
void LCD_Write_4Bit(unsigned char Nibble);
void LCD_CMD(unsigned char CMD);
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL);
void LCD_Write_Char(char);
void LCD_Write_String(char*);
void Backlight();
void noBacklight();
void LCD_SR();
void LCD_SL();
void LCD_Clear();
I2c.c
#include <xc.h>
#include "I2C.h"
unsigned char RS, i2c_add, BackLight_State = LCD_BACKLIGHT;
//---------------[ I2C Routines ]-------------------
//--------------------------------------------------
void I2C__Init()
{
SSPCON = 0x28;
SSPCON2 = 0x00;
SSPSTAT = 0x00;
SSPADD = ((_XTAL_FREQ/4)/I2C_BaudRate) - 1;
SCL_D = 1;
SDA_D = 1;
}
void I2C__Wait()
{
while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
}
void I2C__Start()
{
I2C__Wait();
SEN = 1;
}
void I2C__RepeatedStart()
{
I2C__Wait();
RSEN = 1;
}
void I2C__Stop()
{
I2C__Wait();
PEN = 1;
}
void I2C_ACK(void)
{
ACKDT = 0; // 0 -> ACK
I2C__Wait();
ACKEN = 1; // Send ACK
}
void I2C_NACK(void)
{
ACKDT = 1; // 1 -> NACK
I2C__Wait();
ACKEN = 1; // Send NACK
}
unsigned char I2C__Write(unsigned char data)
{
I2C__Wait();
SSPBUF = data;
while(!SSPIF); // Wait Until Completion
SSPIF = 0;
return ACKSTAT;
}
unsigned char I2C_Read_Byte(void)
{
//---[ Receive & Return A Byte ]---
I2C__Wait();
RCEN = 1; // Enable & Start Reception
while(!SSPIF); // Wait Until Completion
SSPIF = 0; // Clear The Interrupt Flag Bit
I2C__Wait();
return SSPBUF; // Return The Received Byte
}
//======================================================
//---------------[ LCD Routines ]----------------
//------------------------------------------------------
void LCD_Init(unsigned char I2C_Add)
{
i2c_add = I2C_Add;
IO_Expander_Write(0x00);
__delay_ms(30);
LCD_CMD(0x03);
__delay_ms(5);
LCD_CMD(0x03);
__delay_ms(5);
LCD_CMD(0x03);
__delay_ms(5);
LCD_CMD(LCD_RETURN_HOME);
__delay_ms(5);
LCD_CMD(0x20 | (LCD_TYPE << 2));
__delay_ms(50);
LCD_CMD(LCD_TURN_ON);
__delay_ms(50);
LCD_CMD(LCD_CLEAR);
__delay_ms(50);
LCD_CMD(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
__delay_ms(50);
}
void IO_Expander_Write(unsigned char Data)
{
I2C__Start();
I2C__Write(i2c_add);
I2C__Write(Data | BackLight_State);
I2C__Stop();
}
void LCD_Write_4Bit(unsigned char Nibble)
{
// Get The RS Value To LSB OF Data
Nibble |= RS;
IO_Expander_Write(Nibble | 0x04);
IO_Expander_Write(Nibble & 0xFB);
__delay_us(50);
}
void LCD_CMD(unsigned char CMD)
{
RS = 0; // Command Register Select
LCD_Write_4Bit(CMD & 0xF0);
LCD_Write_4Bit((CMD << 4) & 0xF0);
}
void LCD_Write_Char(char Data)
{
RS = 1; // Data Register Select
LCD_Write_4Bit(Data & 0xF0);
LCD_Write_4Bit((Data << 4) & 0xF0);
}
void LCD_Write_String(char* Str)
{
for(int i=0; Str[i]!='\0'; i++)
LCD_Write_Char(Str[i]);
}
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL)
{
switch(ROW)
{
case 2:
LCD_CMD(0xC0 + COL-1);
break;
case 3:
LCD_CMD(0x94 + COL-1);
break;
case 4:
LCD_CMD(0xD4 + COL-1);
break;
// Case 1
default:
LCD_CMD(0x80 + COL-1);
}
}
void Backlight()
{
BackLight_State = LCD_BACKLIGHT;
IO_Expander_Write(0);
}
void noBacklight()
{
BackLight_State = LCD_NOBACKLIGHT;
IO_Expander_Write(0);
}
void LCD_SL()
{
LCD_CMD(0x18);
__delay_us(40);
}
void LCD_SR()
{
LCD_CMD(0x1C);
__delay_us(40);
}
void LCD_Clear()
{
LCD_CMD(0x01);
__delay_us(40);
}
main.c:
#include "I2C.h"
void main(void) {
I2C__Init();
LCD_Init(0x4E); // Initialize LCD module with I2C address = 0x4E
LCD_Set_Cursor(1, 1);
LCD_Write_String(" Welcome To ");
LCD_Set_Cursor(2, 1);
LCD_Write_String(" MicroDigiSoft ");
delay_ms(2500);
while(1)
{
}
return;
}
But I get these Errors:
Screenshot of Error
Screenshot of Error
I am using MikroC and one thing to note is that I have included the system libraries Lcd and Lcd Constants.
How can I fix these errors, and are there any examples of interfacing LCD I2C with microcontrollers apart from this?
You must import the I2C system libray in the the MikroC Library Manager, at the right panel. See the attached image:
I am using Arduino nano ble 33, and I want to covert accelerometer values which are x,y,z into frequencies then these frequencies values need to be sent through the Arduino nano 33 ble. Can someone help me with this issue? Thanks in advance.
Here is my code: The code now only reads the raw data from the accelerometer.
< #include "Arduino.h"
#include <ArduinoBLE.h>
#include "Nano33BLEAccelerometer.h"
// #include "arduinoFFT.h"
#define BLE_BUFFER_SIZES 20
#define BLE_DEVICE_NAME "Nano 33 BLE"
#define BLE_LOCAL_NAME "Accelerometer BLE"
Nano33BLEAccelerometerData accelerometerData;
BLEService BLEAccelerometer("590d65c7-3a0a-4023-a05a-6aaf2f22441c");
BLECharacteristic accelerometerXBLE("0004", BLERead | BLENotify | BLEBroadcast,
BLE_BUFFER_SIZES);
BLECharacteristic accelerometerYBLE("0005", BLERead | BLENotify | BLEBroadcast, BLE_BUFFER_SIZES);
BLECharacteristic accelerometerZBLE("0006", BLERead | BLENotify | BLEBroadcast, BLE_BUFFER_SIZES);
char bleBuffer[BLE_BUFFER_SIZES];
void setup()
{
Serial.begin(115200);
while(!Serial);
if (!BLE.begin())
{
while (1);
}
else
{
BLE.setDeviceName(BLE_DEVICE_NAME);
BLE.setLocalName(BLE_LOCAL_NAME);
BLE.setAdvertisedService(BLEAccelerometer);
BLEAccelerometer.addCharacteristic(accelerometerXBLE);
BLEAccelerometer.addCharacteristic(accelerometerYBLE);
BLEAccelerometer.addCharacteristic(accelerometerZBLE);
BLE.addService(BLEAccelerometer);
BLE.advertise();
Accelerometer.begin();
accelerometerXBLE.writeValue((byte)0x01);
accelerometerYBLE.writeValue((byte)0x01);
accelerometerZBLE.writeValue((byte)0x01);
Serial.println("X, Y, Z");
}
}
void loop()
{
BLEDevice central = BLE.central();
if(central)
{
Serial.println("Connected");
int writeLength;
while(central.connected())
{
if(Accelerometer.pop(accelerometerData))
{
writeLength = sprintf(bleBuffer, "%f", accelerometerData.x);
accelerometerXBLE.writeValue(bleBuffer);
writeLength = sprintf(bleBuffer, "%f", accelerometerData.y);
accelerometerYBLE.writeValue(bleBuffer);
writeLength = sprintf(bleBuffer, "%f", accelerometerData.z);
accelerometerZBLE.writeValue(bleBuffer);
delay(1000);
Serial.printf("%f,%f,%f\r\n", accelerometerData.x, accelerometerData.y,
accelerometerData.z);
}
}
}
} >
What you are asking is not simple. You will need to use a Fourier transformation. Read about it here: https://see.stanford.edu/materials/lsoftaee261/chap8.pdf
When I compile this code ;
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
volatile int state_Led = LOW;
int SerialVal_;
void setup()
{
#define USART_BAUDRATE 9600
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
UBRR0H = (uint8_t)(UBRR_VALUE>>8);
UBRR0L = (uint8_t)UBRR_VALUE;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // Turn on the transmission, reception, and Receive interrupt
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
interrupts();
}
int c = 0;
int b;
void loop()
{
if(Serial.available() > 0); // Error Line
}
ISR(USART_RX_vect)
{
cli();
while(!(UCSR0A&(1<<RXC0))){};
c= UDR0; // clear the USART interrupt
UDR0 = c + 0x0A;
sei();
}
I get the error of "C:\Program Files\Arduino\hardware\arduino\cores\arduino/HardwareSerial.cpp:115: multiple definition of `__vector_18'"
To sum up, if I use interrupt with USART interrupt vector I can't use simple Serial.xxx class methods for a reason that I don't know. I know lots of people are having the same problem. If someone berings the solution, that would be great. Thanks in advance
I have some problem with my own arduino library. Compiler does not recognize my class Platform and says: "error: 'Platform' does not name a type".
Here is the main program code:
#include <Platform.h>
#define MOVE_FORWARD 0xFF
#define MOVE_BACKWARD 0xF0
// Error 'Platform' does not name a type
Platform plt(13, 14, 15);
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.read() == MOVE_FORWARD)
plt.move(5);
if (Serial.read() == MOVE_BACKWARD)
plt.move(-5);
}
Here is the Platform.h code:
#ifndef PLATFORM_H
#define PLATFORM_H
#include <arduino.h>
#include <Motor.h>
class Platform {
public:
Platform(int input_1, int input_2, int enable); // Pins for L293D
void move(int distance);
private:
Motor *m_motors; // All motors connected to one L293D
};
#endif
And implementation of Platform:
#include "Platform.h"
Platform::Platform(int input_1, int input_2, int enable){
m_motors = new Motor(input_1, input_2, enable);
}
void Platform::move(int distance){
byte mm_delay = 100;
byte motor_power = 128;
if (distance > 0)
m_motors->forvard(motor_power);
else if (distance < 0)
m_motors->backward(motor_power);
delay(mm_delay*distance);
m_motors->stop();
}
The behavior of the compiler is pretty strange for me because the Motor library work nice and structure of Platform.h is the same as structure of Motor.h.
From above program it is clear that error report your getting because of below reason . you need to change header include file from #include <Platform.h> to include "Platform.h".
I want send some string to PC via serial bus. In cute com its displaying the string along with some chars are missing and at the starting and end of the string its appending some hex numbers. Why this problem occurring I don't know please help in this issue. My code is here.
#include <avr/io.h>
#include <string.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define USART_BAUDRATE 9600 // Baud Rate value
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void usart_init() {
//Enable communication in duplex mode
UCSR1A = (1 << U2X1);
UCSR1B |= (1 << RXEN1) | (1 << TXEN1); // Turn on the transmission and reception circuitry
UCSR1C &= ~(1 << UMSEL1);
UCSR1C |= (1<<USBS1) | (1 << UCSZ10) | (1 << UCSZ11);
UBRR1L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRR1H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
}
void serial_write(unsigned char data) {
while(!(UCSR1A & (1<<UDRE1)))
;
UDR1 = data;
_delay_ms(10);
}
void transmitString(unsigned char *str) {
int i;
for(i=0;i<strlen(str);i++) {
serial_write(str[i]);
_delay_ms(1);
}
}
int main() {
cli();
usart_init();
unsigned char buffer[20];
strcpy(buffer, "Walk Alone");
while(1) {
transmitString(buffer);
//_delay_ms(250);
}
return 0;
}
Firstly, this question belongs in http://electronics.stackexchange.com
To answer your question, functions strcpy() and strlen() expect a char * and not unsigned char * check here