Native USB port, keyboard, how to toggle VBOF (5V native USB) at PB10 UOTGVBOF

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
A solution has been found, see my last post in this topic! Reply #7
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

I connected a keyboard to the native USB port of the Arduino Due. It only works with the power coming from the PC over the programming USB port.

The moment I use an external power supply (plugged into the Arduino Due power plug), the keyboard does not work any more (because the 5V at the native USB port are switched off).

Is it possible to turn the 5V for the native USB port on by pulling PB10 UOTGVBOF high or low?

Could someone show me some code which toggles UOTGVBOF at PB10.

Attached is an example code, but the keyboard is off (the 5V at the native USB port are off) the moment I connect an external power supply.

I want to use a keyboard or a mouse to control something on the various digital and analogue ports of the Arduino Due while it is on its own power supply (e.g. a 12 V battery and not connected to a PC via its programming port).

I attached the relevant part of the Arduino Due schematics, where the 5V to the native USB are switched off when connected to an external power supply (VIN).

Greetings, Conrad

/*
Keyboard Controller

Shows the output of a USB Keyboard connected to the
native USB controller of an Arduino Due Board.
*/

#include <address.h>
#include <adk.h>
#include <confdescparser.h>
#include <hid.h>
#include <hidboot.h>
#include <hidusagestr.h>
#include <KeyboardController.h>
#include <MouseController.h>
#include <parsetools.h>
#include <Usb.h>
#include <usb_ch9.h>

char inByte = 0; // incoming character from PC
char Key = 0; // incoming character from keyboard
int rawKey = 0; // incomming key as integer from keyboard
int led = 13; // yellow LED on Arduino Due Board

USBHost usb; // USB Controller
KeyboardController keyboard(usb); // Attach Keyboard controller to USB

void setup(){

pinMode(led, OUTPUT);
digitalWrite(led, LOW); // turn LED off

Serial.begin(9600);

establishContact(); // establish contact with PC until a byte is received from PC
}

void loop(){

if (Serial.available() > 0) {
inByte = Serial.read();
Serial.print("from PC : ");
Serial.println(inByte);

if (inByte == 'w') {
// ?????????????????????????
// set VBOF at PB10 UOTGVBOF ????
// turn +5V at native USB off/on ?????
// PIOB->PIO_SODR=PIO_PB10A_UOTGVBOF; //sets UOTGVBOF ???
PIOB->PIO_CODR=PIO_PB10A_UOTGVBOF; //clears UOTGVBOF ???
// ???????????????????????????????????????

Serial.println("UOTGVBOF LOW");
}
digitalWrite(led, LOW); // turn LED off
}
usb.Task();
}

void keyPressed() {
Serial.print("Raw Key: ");
rawKey = keyboard.getKey();
Serial.print(rawKey);
Serial.print(" - Character: ");
Key = rawKey;
Serial.print(Key);
Serial.print(" - OEM: ");
Serial.print(keyboard.getOemKey());
Serial.print(" - mod: ");
Serial.print(keyboard.getModifiers());
Serial.println();

digitalWrite(led, HIGH); // turn LED on

}

void establishContact() {
while (Serial.available() <= 0) {
Serial.println("Send a character!"); // send an initial string to PC
delay(1000);
}
}

May it helps take a look at Page 1108 from the full SAM3xa Manuel

Markus_L811:
May it helps take a look at Page 1108 from the full SAM3xa Manuel

Thank you Markus, this is exactly the right place to look.

My problem: I am such a beginner, that I can not write code to toggle UOTGVBOF. It dose not work with digitalWrite().

From page 1108 of the full SAM3xa user manual:

• VBUSPO: VBus Polarity Off
0: The UOTGVBOF output signal is in its default mode (active high).
1: The UOTGVBOF output signal is inverted (active low).

Greetings, Conrad

conradelektro:

Markus_L811:
May it helps take a look at Page 1108 from the full SAM3xa Manuel

Thank you Markus, this is exactly the right place to look.

My problem: I am such a beginner, that I can not write code to toggle UOTGVBOF. It dose not work with digitalWrite().

From page 1108 of the full SAM3xa user manual:

• VBUSPO: VBus Polarity Off
0: The UOTGVBOF output signal is in its default mode (active high).
1: The UOTGVBOF output signal is inverted (active low).

Greetings, Conrad

I'm not sure but try this line in your viod Setup()

UOTGHS->UOTGHS_CTRL = UOTGHS_CTRL_VBUSPO;

Markus

@Markus:

Wow, your code

UOTGHS->UOTGHS_CTRL = UOTGHS_CTRL_VBUSPO;

turns off the+5V at the native USB port (while the Arduino Due is getting power from the programming USB port). We are on the right track.

Now, please tell me how to toggle the UOTGVBOF the other way.

Thank you, Conrad

conradelektro:
@Markus:

Wow, your code

UOTGHS->UOTGHS_CTRL = UOTGHS_CTRL_VBUSPO;

turns off the+5V at the native USB port (while the Arduino Due is getting power from the programming USB port). We are on the right track.

Now, please tell me how to toggle the UOTGVBOF the other way.

Thank you, Conrad

Try this

UOTGHS->UOTGHS_CTRL = ~UOTGHS_CTRL_VBUSPO;

Markus_L811:
Try this

UOTGHS->UOTGHS_CTRL = ~UOTGHS_CTRL_VBUSPO;

@Markus: I tried this code and it does not work. While on an external power supply the keyboard does still not get +5V from the native USB port.

There are two possibilities, either the code is wrong or the +5V can not be switched to the native USB port while on an external power supply.

UOTGHS->UOTGHS_CTRL = UOTGHS_CTRL_VBUSPO;  while on USB power from PC, switches off 5V at native USB

UOTGHS->UOTGHS_CTRL = ~UOTGHS_CTRL_VBUSPO;  while on USB power from PC, does not bring back 5V at native USB

//while on an external power supply there never is 5V at native USB, and the above code does nothing

I guess the code is wrong, because looking at the schematics of the Arduino Due board, it should be possible to switch on the 5V at the native USB with UOTGHS_CTRL_VBUSPO while on an external power supply. And it should be possible to turn on and off the 5V at the native USB programmatically again and again independently of power from the PC (via the programming USB port) or from an external power supply.

I hope that some person versed in the art of Arduino Due programming can answer this question, but so far no luck.

The question can be rephrased:

Please state some code that safely toggles UOTGHS_CTRL_VBUSPO (PB10 UOTGVBOF) ?

Greetings, Conrad

I found a solution! May be there are better solutions, but the Arduino Due super programmers seem to be absent from this forum, so we will never know.

Put the following code in the setup() function:

void setup(){

// --------------------------------------------------------------------------------------
// This will set 5V to the native USB port even if an external power supply is connected.

PIOB->PIO_PER |= 1<<10; // Never do this once Serial.begin() is called,
PIOB->PIO_OER |= 1<<10; // it will disconnect the programming USB port from the PC.
PIOB->PIO_SODR |= 1<<10; // UOTGVBOF HIGH

// --------------------------------------------------------------------------------------

Serial.begin(9600);
}

The solution code conflicts with the Serial() methods, but if one does it before calling a Serial() method, it will work.

Here a short sketch which shows (in the Serial Monitor) the keys pressed on the keyboard connected to the native USB port.

And the Arduino Due LED can be switched on/off by pressing h or l on the keyboard attached to the native USB port or by pressing h or l on the PC keyboard in case the Serial Monitor is running.

The LED is also switched by directly accessing the registers in the SAM3X8E ARM Cortex-M3 CPU.

/*
 Keyboard Controller

 Shows the output of a USB Keyboard connected to the
 native USB controller of an Arduino Due Board.
 */
 
#include <address.h>
#include <adk.h>
#include <confdescparser.h>
#include <hid.h>
#include <hidboot.h>
#include <hidusagestr.h>
#include <KeyboardController.h>
#include <MouseController.h>
#include <parsetools.h>
#include <Usb.h>
#include <usb_ch9.h>

char inByte = 0; // incoming character from PC
char Key = 0;    // incoming character from keyboard
int rawKey = 0;  // incomming key as integer from keyboard

USBHost usb;     // USB Controller

KeyboardController keyboard(usb);  // Attach Keyboard controller to USB


void setup(){
  
  // --------------------------------------------------------------------------------------
  // This will set 5V to the native USB port even if an external power supply is connected.

  PIOB->PIO_PER |= 1<<10;      // Never do this once Serial.begin() is called,
  PIOB->PIO_OER |= 1<<10;      // it will disconnect the programming USB port from the PC.
  PIOB->PIO_SODR |= 1<<10;     // UOTGVBOF HIGH

  // --------------------------------------------------------------------------------------
  
  Serial.begin(9600);
}


void loop(){
  
  if (Serial.available() > 0) {
     inByte = Serial.read();
     Serial.print("from PC : ");
     Serial.println(inByte);

     if (inByte == 'h') {
            
       PIOB->PIO_PER |= 1<<27;
       PIOB->PIO_OER |= 1<<27;
       PIOB->PIO_SODR |= 1<<27; // LED HIGH, direct access to Pin 27 at I/O PortB
       
       Serial.println("from PC LED ON");
       }

     if (inByte == 'l') {
       
       PIOB->PIO_PER |= 1<<27;
       PIOB->PIO_OER |= 1<<27;      
       PIOB->PIO_CODR |= 1<<27; // LED LOW, direct access to Pin 27 at I/O PortB
             
       Serial.println("from PC LED OUT");     
       }

     }
     
   usb.Task();
}


void keyPressed() {

  Serial.print("Raw Key: ");
  rawKey = keyboard.getKey();
  Serial.print(rawKey);
  Serial.print(" - Character: ");
  Key = rawKey;
  Serial.print(Key);
  Serial.print(" - OEM: ");
  Serial.print(keyboard.getOemKey());
  Serial.print(" - mod: ");
  Serial.print(keyboard.getModifiers()); 
  Serial.println();
  
  if (Key == 'h') {
            
    PIOB->PIO_PER |= 1<<27;
    PIOB->PIO_OER |= 1<<27;
    PIOB->PIO_SODR |= 1<<27; // LED HIGH, direct access to Pin 27 at I/O PortB
       
    Serial.println("from KB LED ON");
    }
       
  if (Key == 'l') {
       
    PIOB->PIO_PER |= 1<<27;
    PIOB->PIO_OER |= 1<<27;      
    PIOB->PIO_CODR |= 1<<27; // LED LOW, direct access to Pin 27 at I/O PortB
             
    Serial.println("from KB LED OUT");     
    }
}

In the directory (on Winows PCs) C:\arduino-1.5.1r2\hardware\arduino\sam\system\CMSIS\Device\ATMEL\sam3xa\html one finds many very useful register references and explications.

Greetings, Conrad

The same problem occurs of course with a mouse on the native USB port (USBHost).

And the same code cures the problem.

Put the following code in the setup() function:

void setup(){

// --------------------------------------------------------------------------------------
// This will set 5V to the native USB port even if an external power supply is connected.

PIOB->PIO_PER |= 1<<10; // Never do this once Serial.begin() is called,
PIOB->PIO_OER |= 1<<10; // it will disconnect the programming USB port from the PC.
PIOB->PIO_SODR |= 1<<10; // UOTGVBOF HIGH

// --------------------------------------------------------------------------------------

Serial.begin(9600);
}

I use this mouse: http://www.conrad.at/ce/de/product/916448

The mouse should be a straight forward Microsoft compatible USB mouse with three buttons, or two buttons and a wheel which can act as a button. The wheel function can not be used with the USBHost library.

The mouse I got has a LED (near the wheel) which will indicate whether there is 5V at the USB or not.

I hope that this problem (5V at the native USB port while on an external power supply) will be solved in the USBHost and Serial Class. Who will do that? Whom shall I contact?

Greetings, Conrad

This code works:

/*
 Mouse Controller Example

 Shows the output of a USB Mouse connected to 
 the Native USB port on an Arduino Due Board.
 */

// Require mouse control library
#include <address.h>
#include <adk.h>
#include <confdescparser.h>
#include <hid.h>
#include <hidboot.h>
#include <hidusagestr.h>
#include <KeyboardController.h>
#include <MouseController.h>
#include <parsetools.h>
#include <Usb.h>
#include <usb_ch9.h>

USBHost usb;                  // Initialize USB Controller
MouseController mouse(usb);   // Attach mouse controller to USB

boolean leftButton = false;   // variables for mouse button states
boolean middleButton = false;
boolean rightButton = false;

char inByte = 0;              // incoming character from PC

void setup()
{
  // --------------------------------------------------------------------------------------
  // This will set 5V to the native USB port even if an external power supply is connected.

  PIOB->PIO_PER |= 1<<10;      // Never do this once Serial.begin() is called,
  PIOB->PIO_OER |= 1<<10;      // it will disconnect the programming USB port from the PC.
  PIOB->PIO_SODR |= 1<<10;     // UOTGVBOF HIGH

  // --------------------------------------------------------------------------------------
  
  Serial.begin(9600);
}

void loop()
{
  
  if (Serial.available() > 0) {
     inByte = Serial.read();
     Serial.print("from PC : ");
     Serial.println(inByte);

     if (inByte == 'h') {
            
       PIOB->PIO_PER |= 1<<27;
       PIOB->PIO_OER |= 1<<27;
       PIOB->PIO_SODR |= 1<<27; // LED HIGH, direct access to Pin 27 at I/O PortB
       
       Serial.println("from PC LED ON");
       }

     if (inByte == 'l') {
       
       PIOB->PIO_PER |= 1<<27;
       PIOB->PIO_OER |= 1<<27;      
       PIOB->PIO_CODR |= 1<<27; // LED LOW, direct access to Pin 27 at I/O PortB
             
       Serial.println("from PC LED OUT");     
       }

     }
       
  usb.Task();   // Process USB tasks
}

// This function intercepts mouse movements
void mouseMoved() {
  Serial.print("Move: ");
  Serial.print(mouse.getXChange());
  Serial.print(", ");
  Serial.println(mouse.getYChange());
}

// This function intercepts mouse movements while a button is pressed
void mouseDragged() {
  Serial.print("DRAG: ");
  Serial.print(mouse.getXChange());
  Serial.print(", ");
  Serial.println(mouse.getYChange());
}

// This function intercepts mouse button press
void mousePressed() {
  Serial.print("Pressed: ");
  if (mouse.getButton(LEFT_BUTTON)){
    Serial.print("L");
    leftButton = true;
  }
  if (mouse.getButton(MIDDLE_BUTTON)){
    Serial.print("M");
    middleButton = true;
  }
  if (mouse.getButton(RIGHT_BUTTON)){
    Serial.print("R");
    Serial.println();
    rightButton = true;
  }
}

// This function intercepts mouse button release
void mouseReleased() {
  Serial.print("Released: ");
  if (!mouse.getButton(LEFT_BUTTON) && leftButton==true) {
    Serial.print("L");
    leftButton = false;
  }
  if (!mouse.getButton(MIDDLE_BUTTON) && middleButton==true) {
    Serial.print("M");
    middleButton = false;
  }
  if (!mouse.getButton(RIGHT_BUTTON) && rightButton==true) {
    Serial.print("R");
    rightButton = false;
  }
  Serial.println();
}

I would not recommend adding this to the USBHost class, since it bypasses a safety feature. The idea of having the USB supply under the USB system control is that in case the supply is short-circuited the USB system will drop power to the port. But by using direct port writes the USB power will always remain on, even in a short circuit condition.

You can get away with this for now so long as the power supply you are using isn't more powerful than is necessary, that way it won't be powerful enough to do any real damage in a short circuit (and if you know your own mouse and keyboard are good it won't be a problem anyway). But I wouldn't add it to the library, in case someone else shorts it.

The proper thing to do is to write code which detects and resets the fault condition but I don't have the right sort of USB cable so can't help.

stimmer:
The proper thing to do is to write code which detects and resets the fault condition but I don't have the right sort of USB cable so can't help.

@stimmer: thank you for the reply.

By "fault condition" you probably mean "there is no 5V at the native USB port". How can this be sensed? Or, at which pin does one have to look in order to find out?

May be by "fault condition" you mean that the device at the native USB port and the power supply are providing 5V to the native USB port. Again, how and where could this be sensed?

Or, by "fault condition" you mean, that the 5V from the native USB are shorted at the other end (where the USB cable leads to, e.g. a faulty keyboard or mouse). Once more, how could this be detected by a program?

Greetings, Conrad

It's the third meaning, detecting a possible short. Also I think it's one of the ways the USB hardware detects a device change.

Anyway I now have a cable and have tried looking at the code. Fortunately it looks like everything needed for correct VBOF control is already in the hardware and software - the problem is that the Due circuit (incorrectly in my opinion) expects the VBOF signal to be active high, but the software is written for it to be active low.

I have been trying the following workaround: in loop(), immediately after the line usb.Task(); add the line uhd_set_vbof_active_high();
This seems to work most of the time but sometimes the USB device doesn't work properly straight away - try pressing reset, or disconnecting the device and reconnecting.
Can you try this and tell me if it works for you?