I have a problem in the at the dead end, line follower robot with Arduino - arduino

Hello everyone I want to make a line follower robot that can detect green intersections. i am making something similar to the RoboCup junior line follower.
the problem is that when the robot gets to a dead end(that has tow green squares)
and it will just go forward.
here is the code(Arduino):
motor pins
int m1p1 = 2 ;
int m1p2 = 3 ;
int m2p1 = 4 ;
int m2p2 = 5 ;
int m3p1 = 6 ;
int m3p2 = 7 ;
int m4p1 = 8 ;
int m4p2 = 9 ;
defining variables
int s ;
int sf ;
int smb;
int t ;
int c1 ;
int c2 ;
int greenPW1 ;
int greenPW2 ;
#define sensorOut1 28
#define sensorOut2 34
void setp
void setup() {
pinMode ( S01 , OUTPUT ) ;
pinMode ( S11 , OUTPUT ) ;
pinMode ( S21 , OUTPUT ) ;
pinMode ( S31 , OUTPUT ) ;
digitalWrite ( S01 , HIGH ) ;
digitalWrite ( S11 , LOW ) ;
pinMode ( sensorOut1 , INPUT ) ;
pinMode ( S02 , OUTPUT ) ;
pinMode ( S12 , OUTPUT ) ;
pinMode ( S22 , OUTPUT ) ;
pinMode ( S32 , OUTPUT ) ;
digitalWrite ( S02 , HIGH ) ;
digitalWrite ( S12 , LOW ) ;
s=255;
sf=70;
smb=200;
}
if statements and void loop
void loop() {
greenPW1 = getGreenPW1 () ;
delay (100) ;
greenPW2 = getGreenPW2 () ;
delay (100) ;
t=0;
c1=0;
c2=0;
while (( digitalRead (IR1) == 0 )&&( digitalRead (IR2) == 0 )&&( digitalRead (IR3) == 0 )&&( digitalRead (IR4) == 0 )&&( digitalRead (IR5) == 0)&&(greenPW1>70)&&(greenPW1<80)){
analogWrite ( m1p1 , 0 ) ;
analogWrite ( m2p1 , s ) ;
analogWrite ( m1p2 , smb ) ;
analogWrite ( m2p2 , 0 ) ;
analogWrite ( m3p1 , 0 ) ;
analogWrite ( m4p1 , s ) ;
analogWrite ( m3p2 , smb ) ;
analogWrite ( m4p2 , 0 ) ;
}
while (( digitalRead (IR1) == 0 )&&( digitalRead (IR2) == 0 )&&( digitalRead (IR3) == 1 )&&( digitalRead (IR4) == 0 )&&( digitalRead (IR5) == 0)&&(greenPW1>70)&&(greenPW1<80)){
analogWrite ( m1p1 , 0 ) ;
analogWrite ( m2p1 , s ) ;
analogWrite ( m1p2 , smb ) ;
analogWrite ( m2p2 , 0 ) ;
analogWrite ( m3p1 , 0 ) ;
analogWrite ( m4p1 , s ) ;
analogWrite ( m3p2 , smb ) ;
analogWrite ( m4p2 , 0 ) ;
}
while (( digitalRead (IR1) == 0 )&&( digitalRead (IR2) == 0 )&&( digitalRead (IR3) == 0 )&&( digitalRead (IR4) == 0 )&&( digitalRead (IR5) == 0)&&(greenPW2>70)&&(greenPW2<80)){
analogWrite ( m3p1 , s ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m3p2 , 0 ) ;
analogWrite ( m4p2 , smb ) ;
analogWrite ( m3p1 , s ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m3p2 , 0 ) ;
analogWrite ( m4p2 , smb ) ;
}
while (( digitalRead (IR1) == 0 )&&( digitalRead (IR2) == 0 )&&( digitalRead (IR3) == 1 )&&( digitalRead (IR4) == 0 )&&( digitalRead (IR5) == 0)&&(greenPW2>70)&&(greenPW2<80)){
analogWrite ( m3p1 , s ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m3p2 , 0 ) ;
analogWrite ( m4p2 , smb ) ;
analogWrite ( m3p1 , s ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m3p2 , 0 ) ;
analogWrite ( m4p2 , smb ) ;
}
while ((greenPW2>70)&&(greenPW2<80)&&(greenPW1>60)&&(greenPW1<70)){
analogWrite ( m1p1 , 0 ) ;
analogWrite ( m1p2 , 0 ) ;
analogWrite ( m2p1 , 0 ) ;
analogWrite ( m2p2 , 0 ) ;
analogWrite ( m3p1 , 0 ) ;
analogWrite ( m3p2 , 0 ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m4p2 , 0 ) ;
delay(2000);
analogWrite ( m1p1 ,200 ) ;
analogWrite ( m1p2 ,200 ) ;
analogWrite ( m2p1 , 0 ) ;
analogWrite ( m2p2 , 0 ) ;
delay(800);
analogWrite ( m3p1 , 200 ) ;
analogWrite ( m3p2 , 200 ) ;
analogWrite ( m4p1 , 0 ) ;
analogWrite ( m4p2 , 0 ) ;
}
}
int getGreenPW1(){
if (c1==0){
digitalWrite ( S21 , HIGH ) ;
digitalWrite ( S31 , HIGH ) ;
int PW1 ;
PW1 = pulseIn ( sensorOut1 , LOW ) ;
return PW1 ;
c1=1;
}
}
int getGreenPW2(){
if (c2==0){
digitalWrite ( S22 , HIGH ) ;
digitalWrite ( S32 , HIGH ) ;
int PW2 ;
PW2 = pulseIn ( sensorOut2 , LOW ) ;
return PW2 ;
c2=1;
}
}

Related

Trying to experiment with some logic in Arduino, how do I make it work?

I am learning to code in arduino.
I am trying to write a code, where I have a number of bottons and from A1-A4 there is a OR logic gate that activates (LED). but if A1-A4 & B0 is high There is and AND gate that activate (LED).
the code is below, let me know what I could do different
int pin_A0 = 26;
int pin_A1 = 22;
int pin_A2 = 23;
int pin_A3 = 24;
int pin_A4 = 25;
int pin_B0 = 40;
void setup() {
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(pin_A0, INPUT);
pinMode(pin_A1, INPUT);
pinMode(pin_A2, INPUT);
pinMode(pin_A3, INPUT);
pinMode(pin_A4, INPUT);
pinMode(pin_B0, INPUT);
}
void loop() {
if ( (digitalRead(pin_A1 || pin_A2 || pin_A3 || pin_A4) == HIGH) ) {
digitalWrite(A0, HIGH);
return;
}
if ( (digitalRead(pin_B0) == HIGH) && (digitalRead(pin_A1 || pin_A2 || pin_A3 || pin_A4) == HIGH)){
digitalWrite(A1, HIGH);
return;
With digitalRead(pin_A1 || pin_A2 || pin_A3 || pin_A4) == HIGH you are using logical OR on those values, then trying to read that pin. What you are doing is:
digitalRead(22 || 23 || 24 || 25) == HIGH
And 22 || 23 || 24 || 25 = 1 since there is at least one non-zero (truthy) value. So you are doing this:
digitalRead(1) == HIGH
Instead, you have to do:
if ((digitalRead(pin_A1) || digitalRead(pin_A2) || digitalRead(pin_A3) || digitalRead(pin_A4)) == HIGH) { ... }
And since HIGH = 1 (truthy) and LOW = 0 (false) you can drop the == HIGH part:
if (digitalRead(pin_A1) || digitalRead(pin_A2) || digitalRead(pin_A3) || digitalRead(pin_A4)) { ... }
You can use less code (DRY) by storing the value:
void loop()
{
bool a_button_pressed = digitalRead(pin_A1) || digitalRead(pin_A2) || digitalRead(pin_A3) || digitalRead(pin_A4);
bool b_button_pressed = digitalRead(pin_B0);
// Note: boolean values converted to int will be 1 or 0
digitalWrite(A0, a_button_pressed);
digitalWrite(A1, a_button_pressed && b_button_pressed);
}
Note: this will turn the leds off when the conditions are false, or 0, which is LOW.

how to solve else/if statement issue?

#include <Wire.h>
#include "DFRobot_LCD.h"
DFRobot_LCD lcd(16, 2); //16 characters and 2 lines of show
#define PH_PIN 25
float voltage,phvalue,temperature = 25;
float acidVoltage = (1990); //buffer solution at 4.o
float neutralVoltage = (1389); //buffer solution at 7.o
const int Sensor_MINvalue1 = 3.8; // +-0.5 from ph 4.0
const int Sensor_MAXvalue1 = 4.1;
const int Sensor_MINvalue2 = 6.8; // +-0.5 from ph 7.0
const int Sensor_MAXvalue2 = 7.1;
const int Sensor_MINvalue3 = 9.8; // +-0.5 from ph 10.0
const int Sensor_MAXvalue3 = 10.1;
void breath(unsigned char color){
for(int i=0; i<255; i++){
lcd.setPWM(color, i);
delay(5);
}
delay(500);
for(int i=254; i>=0; i--){
lcd.setPWM(color, i);
delay(1000);
}
delay (300);
}
void setup()
{
Serial.begin(11520);
// LCD Begin //
lcd.init();
lcd.setCursor(4,0);
lcd.print("Welcome");
delay(3000);
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Reading PH");
delay(5000);
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Please Wait");
delay(5000);
lcd.clear();
}
void loop()
{
static unsigned long timepoint = millis();
if(millis()-timepoint>1000U){
timepoint = millis();
// timepoint = read temperature
voltage = analogRead (PH_PIN)/4095.0*3300;
float slope = (7.0-4.0)/((neutralVoltage-1500)/30 - (acidVoltage-1500)/3.0);
float intercept = 7.0 - slope*(neutralVoltage-1500)/3.0;
phvalue = slope*(voltage-1500)/3.0 + intercept; // y=k*x + b [formula]
if( phvalue < Sensor_MAXvalue1 && phvalue > Sensor_MINvalue1 ){ //if( phvalue < 4.1 && phvalue > 3.8 )
Serial.print("Voltage:");
Serial.print(voltage,1);
Serial.print("PH:");
Serial.println(phvalue,2);
//LCD setting 16x2
lcd.setCursor(0,0);
lcd.print("PH : ");
lcd.print(phvalue,2);
lcd.setCursor(0,1);
lcd.print("Volt : ");
lcd.print(voltage/1000,2);
if( phvalue < Sensor_MINvalue1 && phvalue > Sensor_MAXvalue1 ){
lcd.setCursor(3,0);
lcd.print("Dosing is required");
delay(5000);
lcd.clear();
}
}
else if (phvalue < Sensor_MAXvalue2 && phvalue > Sensor_MINvalue2){ //if( phvalue < 7.1 && phvalue > 6.8 )
Serial.print("Voltage:");
Serial.print(voltage,1);
Serial.print("PH:");
Serial.println(phvalue,2);
//LCD setting 16x2
lcd.setCursor(0,0);
lcd.print("PH : ");
lcd.print(phvalue,2);
lcd.setCursor(0,1);
lcd.print("Volt : ");
lcd.print(voltage/1000,2);
if( phvalue < Sensor_MINvalue2 && phvalue > Sensor_MAXvalue2 ){
lcd.setCursor(3,0);
lcd.print("Dosing is required");
delay(5000);
lcd.clear();
}
}
else (phvalue < Sensor_MAXvalue3 && phvalue > Sensor_MINvalue3); { //if( phvalue < 10.1 && phvalue > 9.8 )
Serial.print("Voltage:");
Serial.print(voltage,1);
Serial.print("PH:");
Serial.println(phvalue,2);
//LCD setting 16x2
lcd.setCursor(0,0);
lcd.print("PH : ");
lcd.print(phvalue,2);
lcd.setCursor(0,1);
lcd.print("Volt : ");
lcd.print(voltage/1000,2);
if( phvalue < Sensor_MINvalue3 && phvalue > Sensor_MAXvalue3 ){
lcd.setCursor(3,0);
lcd.print("Dosing is required");
delay(5000);
lcd.clear();
}
}
}
}
that is my code, after applying the code it is not working, I am trying so that it reads a range of values so that it reads the ph value and show me the values for example if the ph = 6.8-7.1 it will show the ph, if the value is below or above it will print 'dosing is required but now it is not showing it. i am unsure if i should create a main so that i can seperate the if, else if, esle statemant
if( phvalue < Sensor_MINvalue1 && phvalue > Sensor_MAXvalue1 )
How can phvalue be smaller than your min and larger than your max at the same time?
You should use logical or || here.
Same for
if( phvalue < Sensor_MINvalue2 && phvalue > Sensor_MAXvalue2 )
and
if( phvalue < Sensor_MINvalue3 && phvalue > Sensor_MAXvalue3 )

How to control the Led's in a 5*5 Led - Matrix with the help of 5*5 push-button

I want two Led's ( Led 1 and Led 3 ) in a 5*5 Led - Matrix to light up and when the corresponding buttons in the 5*5 push-button are pressed the Led's turns off and another two Led's ( Led 3 and Led 5 ) should light up
and when the corresponding buttons are pressed the Led's turns off and another two led's ( Led 5 and Led 11 ) should light up and the process continues for next set of Led's ( Led 11 and Led 13 ) and the next set is ( Led 13 and Led 15 ) and the next set is ( Led 15 and Led 17 ) and ( Led 17 and Led 21 ) and (Led 21 and Led 23 ) and ( Led 23 and Led 25 ).
The code I have written is :
/* If both "first_key_pressed" and "second_key_pressed", we will make the next two LEDs glow and set these two values to zero again
Initially, LEDs 1 and 3 are glowing, so it is declared that the Led 1 is currently first_in_position and Led 3 is currently second_in_position.
Once 1 and 3 are pressed, we will change this two values to first_in_position = '3' and second_in_position = '5'
The method set_next_expected_leds does this job.
*/
#include <Keypad.h>
const byte rows = 5;
const byte cols = 5;
char keys[rows][cols] = {
{'1','2','3','4','5'},
{'6','7','8','9','A'},
{'B','C','D','E','F'},
{'G','H','I','J','K'},
{'L','M','N','O','P'}
};
byte rowPins[rows] = {40, 39 , 38 , 37 , 36 };
byte colPins[cols] = { 35 , 34 ,33 , 32 , 31 };
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );
int Led_Rows[] = { 2 , 3 , 4 ,5 ,6 } ;
int Led_Columns[] = { 7 , 8 , 9 , 10 , 11 };
int Loop_Count = 5 ;
int first_key_pressed = 0;
int second_key_pressed = 0;
char first_in_position = '1';
char second_in_position = '3';
int Wait_Time = 1000 ;
int i = 0 ;
int j = 0 ;
int x = 0 ;
int y = 0 ;
int c = 0 ;
void setup() {
Serial.begin(9600);
for(int i=0;i<5;i++){
pinMode(Led_Rows[i], OUTPUT);
digitalWrite(Led_Rows[i],LOW);
pinMode(Led_Columns[i], OUTPUT);
digitalWrite(Led_Columns[i],HIGH);
}
Led_Glow(0,0);
Led_Glow(0,2);
}
void All_On(){
for( i = 0 ; i < Loop_Count ; i++ ){
digitalWrite(Led_Rows[i],HIGH);
while( j < Loop_Count ){
digitalWrite(Led_Columns[j],LOW);
j++ ;
}
}
j = 0 ;
}
void All_Off(){
for( i = 0 ; i < Loop_Count ; i++ ){
digitalWrite(Led_Rows[i],LOW);
digitalWrite(Led_Columns[i],HIGH);
}
}
void Led_Glow( int a , int b ){
digitalWrite(Led_Rows[a],HIGH);
digitalWrite(Led_Columns[b],LOW);
}
void Led_Dim( int a ,int b ){
digitalWrite(Led_Rows[a],LOW);
digitalWrite(Led_Columns[b],HIGH);
}
void check_for_position(int c) {
if (first_in_position == c) {
first_key_pressed = 1;
} else if (second_in_position == c) {
second_key_pressed = 1;
}
}
void set_next_expected_leds() {
if (first_in_position == '1') {
first_in_position = '3';
second_in_position = '5';
Led_Glow(0,2);
Led_Glow(0,4);
} else if (first_in_position == '3') {
first_in_position = '5';
second_in_position = 'B';
Led_Glow(0,4);
Led_Glow(2,0);
} else if (first_in_position == '5') {
first_in_position = 'B';
second_in_position = 'D';
Led_Glow(2,0);
Led_Glow(2,2);
} else if (first_in_position == 'B') {
first_in_position = 'D';
second_in_position = 'F';
Led_Glow(2,2);
Led_Glow(2,4);
} else if (first_in_position == 'D') {
first_in_position = 'F';
second_in_position = 'L';
Led_Glow(2,4);
Led_Glow(4,0);
} else if (first_in_position == 'F') {
first_in_position = 'L';
second_in_position = 'N';
Led_Glow(4,0);
Led_Glow(4,2);
} else if (first_in_position == 'L') {
first_in_position = 'N';
second_in_position = 'P';
Led_Glow(4,2);
Led_Glow(4,4);
} else if (first_in_position == 'N') {
} else if (first_in_position == 'P') {
}
first_key_pressed = 0;
second_key_pressed = 0;
}
void loop() {
char key = keypad.getKey();
switch (key) {
case '1':
check_for_position('1');
Led_Dim(0, 0);
break;
case '3':
check_for_position('3');
Led_Dim(0, 2);
break;
case '5':
check_for_position('5');
Led_Dim(0, 4);
break;
case 'B':
check_for_position('B');
Led_Dim(2, 0);
break;
case 'D':
check_for_position('D');
Led_Dim(2, 2);
break;
case 'F':
check_for_position('F');
Led_Dim(2, 4);
break;
case 'L':
check_for_position('L');
Led_Dim(4, 0);
break;
case 'N':
check_for_position('N');
Led_Dim(4, 2);
break;
case 'P':
check_for_position('P');
Led_Dim(4, 4);
}
if(first_key_pressed == 1 && second_key_pressed == 1) {
set_next_expected_leds();
}
}
Expected Result: The user can press button 1 or button 3 in the first step if he presses button 1 the led-1 should go off and after pressing button 3 the led-3 should go off and another set of LEDs (Led-3 and Led-5) should glow.
NOTE: The user has the right to press button-3 first and then button-1 then also first led-3 should go off and then led-1 should go off and then the next set of LEDs can glow.
Actual Result: If I press button 1 both led-1 and led-3 goes off and also when I press Button-3 some random led's start blinking.

ESP32's wireless access disrupts MPU9250 reading

I'm writing a program which reads MPU9250's accelerometer&gyro data using MPU9250's internal FIFO and serves web interface.
Without web access, everything is fine.
However, on the exact timing of web request, bytes read on that timing is changed.
My current code just simply shows template webpage and prints IMU accelerometer value only if its magnitude is greater than 2.5. So, if I do not touch MPU9250 sensor, its value should be between 0.9~1.1. However, it prints some wrong values greater than 2.5 when the webpage is refreshed (currently auto-refreshing in 0.5 seconds ) although MPU9250 sensor is not touched at all.
I'm using LOLIN D32 PRO board. and MPU9250 is connected its default VSPI bus.
I read MPU 9250's FIFO data on arduino's loop function as follows,
while( readBytes = spiread_fifo( buffer + readBytes_all / 2 ) )
readBytes_all += readBytes;
if ( readBytes_all == 0 )
return;
if( digitalRead( 4 ) == 1 ){
int x = buffer[ 0 ];
int y = buffer[ 1 ];
int z = buffer[ 2 ];
double m = sqrt( x * x + y * y + z * z ) / 2048;
if( m > 2.5 )
Serial.println( m );
and spiread_fifo is defined as follows
int spiread_fifo( volatile short * buffer ) {
int fifo_len = spiread( 0x72 ) * 256 + spiread( 0x73 );
if ( fifo_len > 512 )
return -1;
if ( fifo_len == 0 )
return 0;
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( 0x74 | 0x80 );
MPU9250.transfer( 0x00 ); // if I use SPI CLOCK more than 8~12Mhz, it gives me duplicated byte at the beginning. So just drop one of them.
for ( int i = 0; i < 3; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
for ( int i = 3; i < fifo_len / 2; i++ )
MPU9250.transfer16( 0x00 );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
for ( int i = 0; i < 12; i++ )
__asm__ __volatile__ ("nop\n\t");
return fifo_len;
}
If I do not touch or exert any force on MPU9250, serial console should be silent and it actually does if there's no ESP32's webserber access. However it gives some random value on the timing of webpage access, like follows. ( single value per single webpage access )
15.53
16.11
15.60
13.59
16.86
2.55
2.55
3.85
3.85
3.37
6.79
2.63
2.56
5.80
10.18
5.88
3.65
5.80
5.48
2.95
4.01
4.01
3.10
2.90
3.17
9.31
14.97
7.08
16.29
which are totally abnormal values.
My guesses are,
strong RF signal affects SPI bus so signals are altered.
wifi TX routine is called during MPU9250 FIFO readout process and it causes data drop during FIFO read.
Whatever the reason is, I don't know how to fix the problem.
Any possible causes/solutions would be appreciated.
Belows are my current wiring. However, nothing's special. MPU9250 is connected to default VSPI port and INT pin is connected to GPIO34. other remaining connection is not used.
PICTURE 1
PICTURE 2
full source codes below for your reference.
MAIN CODE :
extern volatile int cnt;
volatile short* buffer;
volatile short* buffer2;
volatile unsigned long *timestamp;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
void printHex( int num, int precision) {
char tmp[16];
char format[128];
sprintf(format, "%%.%dX ", precision);
sprintf(tmp, format, num);
if ( strlen( tmp ) > precision + 1 ) {
int l = strlen( tmp ) - precision - 1;
for ( int i = 0; i < precision + 2; i++ ) {
tmp[ i ] = tmp[ i + l ];
}
}
Serial.print(tmp);
}
void setup() {
Serial.begin( 2000000 );
Serial.println( "Turning on...." );
buffer = ( short * )ps_malloc( 1000000 );
buffer2 = ( short * )ps_malloc( 1000000 );
BUTTONSetup();
MPU9250Setup();
OTASetup();
WEBSERVERSetup();
Serial.println( "Setup finished." );
}
void loop() {
OTAHandle();
WEBSERVERHandle();
int readBytes = 0, readBytes_all = 0;
while( readBytes = spiread_fifo( buffer + readBytes_all / 2 ) )
readBytes_all += readBytes;
if ( readBytes_all == 0 )
return;
if( digitalRead( 4 ) == 1 ){
int x = buffer[ 0 ];
int y = buffer[ 1 ];
int z = buffer[ 2 ];
double m = sqrt( x * x + y * y + z * z ) / 2048;
if( m > 2.5 )
Serial.println( m );
BUTTONHandle();
}
}
MPU9250 CODE :
#include <SPI.h>
#define SCK 18
#define MISO 19
#define MOSI 23
#define SS 5
#define INT 34
SPIClass MPU9250( VSPI );
SPISettings settingsA( 1000000, MSBFIRST, SPI_MODE3 );
SPISettings settingsB( 20000000, MSBFIRST, SPI_MODE3 );
volatile int cnt = 0;
void IRAM_ATTR onInterrupt() {
portENTER_CRITICAL_ISR(&mux);
cnt++;
portEXIT_CRITICAL_ISR(&mux);
}
void spiwrite( byte a, byte b ) {
MPU9250.beginTransaction( settingsA );
digitalWrite( SS, LOW );
MPU9250.transfer( a );
MPU9250.transfer( b );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
}
byte spiread( byte a ) {
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( a | 0x80 );
byte r = MPU9250.transfer( 0x00 );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
return r;
}
int spiread_fifo( volatile short * buffer ) {
int fifo_len = spiread( 0x72 ) * 256 + spiread( 0x73 );
// fifo_len += 12;
// fifo_len = fifo_len / 12 * 12;
if ( fifo_len > 512 )
return -1;
if ( fifo_len == 0 )
return 0;
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( 0x74 | 0x80 );
MPU9250.transfer( 0x00 ); // if I use SPI CLOCK more than 8~12Mhz, it gives me duplicated byte at the beginning. So just drop one of them.
for ( int i = 0; i < 3; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
for ( int i = 3; i < fifo_len / 2; i++ )
MPU9250.transfer16( 0x00 );
// for( int i = fifo_len / 2 + 1; i < fifo_len; i++ )
// buffer[ i ] = 0;
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
for ( int i = 0; i < 12; i++ )
__asm__ __volatile__ ("nop\n\t");
return fifo_len;
}
void spiread_raw( volatile short * buffer ) {
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( 0x3b | 0x80 );
for ( int i = 0; i < 3; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
for ( int i = 0; i < 12; i++ )
__asm__ __volatile__ ("nop\n\t");
}
void spiread_raw_gyr( volatile short * buffer ) {
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( 0x43 | 0x80 );
for ( int i = 0; i < 3; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
for ( int i = 0; i < 12; i++ )
__asm__ __volatile__ ("nop\n\t");
}
void spiread_raw_accgyr( volatile short * buffer ) {
MPU9250.beginTransaction( settingsB );
digitalWrite( SS, LOW );
MPU9250.transfer( 0x3b | 0x80 );
for ( int i = 0; i < 3; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
MPU9250.transfer16( 0x00 );
for ( int i = 3; i < 6; i++ )
buffer[ i ] = MPU9250.transfer16( 0x00 );
digitalWrite( SS, HIGH );
MPU9250.endTransaction();
for ( int i = 0; i < 12; i++ )
__asm__ __volatile__ ("nop\n\t");
}
void MPU9250Setup(){
pinMode( SS, OUTPUT );
pinMode( SCK, OUTPUT );
pinMode( MOSI, OUTPUT );
pinMode( INT, INPUT_PULLUP );
pinMode( MISO, INPUT );
pinMode( 4, INPUT );
MPU9250.begin( SCK, MISO, MOSI, SS ); //CLK,MISO,MOIS,SS
attachInterrupt( digitalPinToInterrupt( INT ), onInterrupt, FALLING );
spiwrite( 0x68, 0x07 );
spiwrite( 0x6A, 0x55 ); // FIFO_EN = 1, FIFO_RST = 1;
spiwrite( 0x19, 0x00 ); // SMPLRT_DIV = 0
spiwrite( 0x1B, 0x18 ); // GYRO_FS_SEL = 3, Fchoice_b = 0
spiwrite( 0x1C, 0x18 ); // ACCEL_FS_SEL = 3
spiwrite( 0x1D, 0x08 ); // accel_fchoice_b = 1
// spiwrite( 0x23, 0x78 ); // TEMP_OUT = 0, GYRO_XOUT = 1, GYRO_YOUT = 1, GYRO_ZOUT = 1, ACCEL = 1
// spiwrite( 0x23, 0x79 ); // TEMP_OUT = 0, GYRO_XOUT = 0, GYRO_YOUT = 0, GYRO_ZOUT = 0, ACCEL = 1
spiwrite( 0x23, 0x08 ); // TEMP_OUT = 0, GYRO_XOUT = 0, GYRO_YOUT = 0, GYRO_ZOUT = 0, ACCEL = 1
spiwrite( 0x37, 0x10 ); // INT_ANYRD_2CLEAR = 1
spiwrite( 0x38, 0xC1 ); // ACTL = 1, OPEN = 1, RAW_RDY_EN = 1
spiwrite( 0x1A, 0x07 ); // FIFO_MODE = 0, EXT_SYNC_SET = 0, DLPF_CFG = 7
}
OTA firmware CODE :
#include <WiFi.h>
#include "esp_wifi.h"
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "XXXXXX";
const char* password = "XXXXXX";
void OTASetup(){
delay( 100 );
esp_wifi_set_max_tx_power( -100 );
WiFi.mode( WIFI_STA );
WiFi.setHostname( "LOLIN_D32_PRO_Sunkyue" );
delay( 100 );
WiFi.begin( ssid, password );
while( WiFi.waitForConnectResult() != WL_CONNECTED ){
Serial.println( "Connection Failed! Rebooting..." );
delay( 10 );
ESP.restart();
}
ArduinoOTA.setPort(53232);
ArduinoOTA.setHostname("LOLIN_D32_PRO_Sunkyue");
ArduinoOTA.setPassword("XXXXXX");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void OTAHandle(){
ArduinoOTA.handle();
}
WEBSERVER CODE :
#include <WiFiClient.h>
#include <WebServer.h>
WebServer server(80);
void handleRoot() {
char temp[400];
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
snprintf(temp, 400,
"<html>\
<head>\
<meta http-equiv='refresh' content='0.5'/>\
<title>ESP32 Demo</title>\
<style>\
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
</style>\
</head>\
<body>\
<h1>Hello from ESP32!</h1>\
<p>Uptime: %02d:%02d:%02d</p>\
<img src=\"/test.svg\" />\
</body>\
</html>",
hr, min % 60, sec % 60
);
server.send(200, "text/html", temp);
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void drawGraph() {
String out = "";
char temp[100];
out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
out += "<g stroke=\"black\">\n";
int y = rand() % 130;
for (int x = 10; x < 390; x += 10) {
int y2 = rand() % 130;
sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
out += temp;
y = y2;
}
out += "</g>\n</svg>\n";
server.send(200, "image/svg+xml", out);
}
void WEBSERVERSetup(){
if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/test.svg", drawGraph);
server.on("/inline", []() {
server.send(200, "text/plain", "this works as well");
});
server.onNotFound(handleNotFound);
server.begin();
}
void WEBSERVERHandle(){
server.handleClient();
}
I can see two solutions for a uni-processor solution(since you have not stated the final goals one may be more optimal than the other):
If it is ok to miss approximately 15-25 ms of data(a tap of the sensor should still register,) Change the spiread_fifo(...) to spiread_raw_accgyr(buffer) in the loop(). This will read the current values into the buffer at the time of the execution. This would definitely not be appropriate for position calculations or calculations of seismic events.
Read and analyze the required data in an interrupt routine(either the hardware pin from the MPU9250, or a timer), since the web client is much more forgiving of delays(within reason).
Either way, the calculations should be optimized to reduce the instruction count(the ESP32 does not have an FPU, so all of the floating point operations must be emulated in software):
The lines:
double m = sqrt( x * x + y * y + z * z ) / 2048;
if( m > 2.5 )
Can be simplified (if perfect (spherical) accuracy is required) by algebraically squaring both sides of the equation to:
double m = (x * x + y * y + z * z) / 4194304;
if (m > 6.25)
Or(preferably, but with slightly less accuracy when combining the axes):
double m = ((abs(x) + abs(y) + abs(z)) / 2048); // Manhattan distance(a diamond in 2D, a four sided, double pyramid in 3d)
if (m > 2.5)
The last line on page 6 of the MPU9250 Datasheet:
states:
1MHz SPI serial interface for communicating with all registers
The next line:
20MHz SPI serial interface for reading sensor and interrupt registers
The FIFO register(Page 27 section 4.17 of the datasheet calls the FIFO a register) is not a sensor nor an interrupt register; therefore communications should be limited to 1 MHZ. Any scanning above this rate MAY(and will in the case of out of phase requests) give invalid/inconstant results.
I have not been able to find a reference for the MPU9250 library, or the commands given, to verify this is the case in your code.

Process information in OpenBSD

I am new to OpenBSD. I have worked on Linux before. I am looking for the directory where I can find the information about the processes running currently. In Linux, we have /proc directory where the entire list is present. But I can not find a similar setup in OpenBSD 4.6. I know there are commands like ps, top and sysctl but I want to get that information through a C code.
procfs in the BSDs is either deprecated or removed altogether, sorry.
That being said, it's also quite usual to have the sources for your system under /usr/src, so you can look at them if you really need to.
Or you can just browse them on the web, eg http://bxr.su/o/bin/ps/ps.c
You can use sysctl to get the running processes in an array of kinfo_proc structures, this type is defined in:
/usr/include/sys/sysctl.h
The top command uses a function named getprocs that works this way, it's defined in:
/usr/src/usr.bin/top/machine.c
The next utility outputs information of all running processes using a slightly modified version of getprocs:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <kvm.h>
#include <sys/sysctl.h>
#define TRUE 1
#define FALSE 0
struct kinfo_proc * getprocs( int * count, int threads )
{
struct kinfo_proc * procbase = NULL ;
unsigned int maxslp ;
size_t size = sizeof( maxslp ) ;
int maxslp_mib[] = { CTL_VM, VM_MAXSLP } ;
int mib[6] =
{
CTL_KERN,
KERN_PROC,
threads ? KERN_PROC_KTHREAD | KERN_PROC_SHOW_THREADS : KERN_PROC_KTHREAD,
0,
sizeof( struct kinfo_proc ),
0
} ;
if( sysctl( maxslp_mib, 2, &maxslp, &size, NULL, 0 ) == -1 )
{
perror( "list" ) ;
return NULL ;
}
retry:
if( sysctl( mib, 6, NULL, &size, NULL, 0 ) == -1 )
{
perror( "list" ) ;
return NULL ;
}
size = 5 * size / 4 ; /* extra slop */
procbase = (struct kinfo_proc *)malloc( size ) ;
if( procbase == NULL )
{
perror( "list" ) ;
return NULL ;
}
mib[5] = (int)( size / sizeof( struct kinfo_proc ) ) ;
if( sysctl( mib, 6, procbase, &size, NULL, 0 ) )
{
if( errno == ENOMEM )
{
free( procbase ) ;
goto retry;
}
perror( "list" ) ;
return NULL ;
}
*count = (int)( size / sizeof( struct kinfo_proc ) ) ;
return procbase ;
}
int showinfo( int threads )
{
struct kinfo_proc * list, * proc ;
int count, i ;
if( ( list = getprocs( &count, threads ) ) == NULL )
{
return 1 ;
}
proc = list ;
if( threads )
{
for( i = 0 ; i < count ; ++i, ++proc )
{
if( proc->p_tid != -1 )
{
printf( "%s: pid: %d (tid: %d)\n", proc->p_comm, proc->p_pid, proc->p_tid ) ;
}
}
}
else
{
for( i = 0 ; i < count ; ++i, ++proc )
{
printf( "%s: pid: %d\n", proc->p_comm, proc->p_pid ) ;
}
}
return 0 ;
}
int main( int argc, char * argv[] )
{
if( argc == 1 )
{
return showinfo( FALSE ) ;
}
else if( argc == 2 && ( !strcmp( argv[1], "-t" ) || !strcmp( argv[1], "--threads" ) ) )
{
return showinfo( TRUE ) ;
}
else
{
printf( "Usage:\n" ) ;
printf( " list [-h] [-t]\n\n" ) ;
printf( "Options:\n" ) ;
printf( " -h, --help Print this information\n" ) ;
printf( " -t, --threads Show threads\n\n" ) ;
return 0 ;
}
}

Resources