Description
Hardware:
Board: espressif dev board v4 - ESP32-WROVER-IE 8MB FLASH
Core Installation version: 1.0.3
IDE name: Arduino IDE
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 10
Description:
For my application I need to switch a port pin between being an output port and being a serial port. This is for the automotive k-line protocol - you need to pull the k-line low for 25ms then start sending serial comms 25ms later.
This is the KWP2000 fast-init protocol. And it may need to be re-done if the link times out etc. And I may need to try a different init type if fast-init repeatedly fails, such as KWP2000 slow-init, or ISO9141 5 baud init. I also need to run 2 separate k-lines, which run independently. So as you can see, simply resetting the machine and always stating up with the correct sequence of events won't work. It really needs to be switchable on the fly to properly support the SAE protocol.
The code works fine on an Arduino Mega2650, but on ESP32 it doesn't work.
I made a simple sketch using the blink demo as a base.
- I start up by toggling the port every 25ms. This works fine using a scope on the pin.
- After 10s I change the port to a serial port, then every 100ms I send a byte. This works fine.
- After a further 10s I change back to an output port and toggle at 25ms. This doesn't work, the port remains HIGH.
- After a further 10s I change back to serial. This works fine.
- goto 3
I also tried using Serial2 directly without the hardwareSerial instantiation, with the same results. I set up 2 ports in the sketch but specifically I need the Tx port to work "ledPin2".
I really need this to work to be able to adhere to the KWP2000 k-line serial protocol.
Sketch:
/*
Blink without Delay
Turns on and off a light emitting diode (LED) connected to a digital pin,
without using the delay() function. This means that other code can run at the
same time without being interrupted by the LED code.
The circuit:
- Use the onboard LED.
- Note: Most Arduinos have an on-board LED you can control. On the UNO, MEGA
and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN
is set to the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your
Arduino model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald
modified 9 Jan 2017
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
#include <HardwareSerial.h>
// constants won't change. Used here to set a pin number:
const int ledPin = 19;// the number of the LED pin
const int ledPin2 = 2;
// Variables will change:
int ledState = LOW; // ledState used to set the LED
bool serialActive = false; // true when set to serial port
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long previousPortSwitchMillis = millis();
// constants won't change:
const long interval = 25; // interval at which to blink (milliseconds)
const long portSwitchInterval = 10000; // interval at which to switch to serial port
HardwareSerial testPort(2);
#define TEST_PORT testPort // set to: Serial2 or testPort to use HardwareSerial library
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
Serial.begin(115200);
Serial.println("Started in OUTPUT mode");
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if(serialActive)
{
static unsigned long lastSend;
if((currentMillis - lastSend) > 50) {
//send abyte
TEST_PORT.write(".");
Serial.print(".");
lastSend = currentMillis;
}
}
else if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
digitalWrite(ledPin2, ledState);
}
if (currentMillis - previousPortSwitchMillis >= portSwitchInterval) {
// save the last time you switched port
previousPortSwitchMillis = currentMillis;
if(serialActive){
Serial.println("");
Serial.println("Serial.end");
Serial.println("OUTPUT mode begin");
TEST_PORT.end();
//change back to outputs
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
serialActive = false;
}
else{
//change to serial
//change to inputs to disable internal pullups
pinMode(ledPin, INPUT);
pinMode(ledPin2, INPUT);
Serial.println("Serial.begin");
TEST_PORT.begin(9600, SERIAL_8N1, ledPin, ledPin2);
serialActive = true;
}
}
}