Raspberry PICO not working with message port, named hardware

Discuss suspected bugs with other users and Sim Innovations Staff

Moderators: russ, Ralph

Message
Author
wendy
Posts: 46
Joined: Sun Aug 26, 2018 7:48 am
Contact:

Raspberry PICO not working with message port, named hardware

#1 Post by wendy »

Experimenting with PICO via the messageport but I cannot get it to work, Air Manager does not see my PICO device.

When I check the wiki page "SiMessagePort (constructor) there is a entry under "device" called "SI_MESSAGE_PORT_DEVICE_RPI_PICO".
However using this entry in a sketch AIR MANAGER does not detect the device. The same sketch with Arduino Nano works perfect.

I have had a look in the source file si_message_port.c and I don't see the RPI_PICO entry, so I think it is not handled.

Is there a solution for this ?

Regards, Wendy

SimPassion
Posts: 5336
Joined: Thu Jul 27, 2017 12:22 am

Re: Raspberry PICO not working with message port, named hardware

#2 Post by SimPassion »

Hi @wendy, here's some inputs : https://siminnovations.com/forums/viewt ... 116#p47116

Gilles

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Raspberry PICO not working with message port, named hardware

#3 Post by jph »

Hi Wendy,
AM appears to be not handling the com port negotiations properly with the VCP on the modern processors (virtual com port). This is not restricted to pico. It is identical on the Nucleo devices as well (STM32). I am hoping that @Corjan could address this when he gets time ? (if you could please Corjan)

Here is a work around and details of the issue.

With any VCP on the modern processors the compiler completely ignores the baud rate in Serial.begin(xxxxxx) - it is meaningless.
It relies on the the device connecting (AM in this case) to do appropriate handshaking and the baud rate is then set to the speed of the negotiator (AM in this case)
For whatever reason this is not happening correctly from AM.

AM will sit there for ever with no response from the micro device.

The work around is to use ANY program such as any terminal emulator or even the Arduino serial monitor and simply open a session - you do not have to do anything at all, just open and immediate close (with the session set to 115200,N,8,1)
Then start AM, add the device com port and voila - it will work perfectly. You can close down AM and re-open it and all will be ok but you will need to use any other program to first signal the correct parameters to the micro's vcp (the 115200,N,8,1 that AM is working with) when the micro is first connected to USB.

I ended up using 'plink' which is a command line version of 'putty' https://zzz.bwh.harvard.edu/plink/downl ... l#download
I use the following batch file (add or change the com ports to whatever you are using)

Code: Select all

@echo off
start "" plink.exe -serial \\.\COM11 -sercfg 115200,8,1,N 
start "" plink.exe -serial \\.\COM14 -sercfg 115200,8,1,N 
start "" plink.exe -serial \\.\COM17 -sercfg 115200,8,1,N 
taskkill /im plink.exe
start "" "C:\Program Files\Air Manager\Bootloader.exe"
exit /b
Hmm, I just noticed Wendy that I actually talked about this to you here - This may also assist Corjan ?. (If you need any other info Corjan please let me know)
https://siminnovations.com/forums/viewt ... o&start=30

The pico will work perfectly then, until the device is next reset.

As for the device (PICO) being listed in the sketch, well, it 'can' be added back in but it still will not work due to the incorrect com port negotiations. You can, for now, just call it anything - call it an UNO ... it doenst matter at all to messageport as it has no concept of the actual TYPE of device it is communicating with. The 'name' we assign the device is just for information. Hopefully it can be added back in officially when the issue is identified.

Joe
Last edited by jph on Mon Sep 05, 2022 2:41 pm, edited 1 time in total.
Joe. CISSP, MSc.

wendy
Posts: 46
Joined: Sun Aug 26, 2018 7:48 am
Contact:

Re: Raspberry PICO not working with message port, named hardware

#4 Post by wendy »

Thanks Joe.

I just opened the serial monitor from Arduino and immediately closed it. I started Air Manager and it added "Hardware Port (D) with a question mark in front of it.
Is this supposed to work now ??

Going to test further now but hoping this can be resolved.

@Gilles
Thanks

Regards, Wendy

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Raspberry PICO not working with message port, named hardware

#5 Post by jph »

Hi Wendy,
For now, in both the Arduino sketch AND AM call the device mega or uno
Best to just use the standard test sketch - dont try to call it anything else at this stage.

The when the pico sketch is compiled and uploaded open the serial monitor set to 115200 (or plink / putty or any terminal program) and immediately close it.
Then add the com port for the device in AM under devices as Arduino.
Then the device will be seen and sign on as whatever you named it - mega or uno.
the hardware port means you have the naming wrong in the sketch I believe as it cannot enumerate it.

for a test, then in the sketch use

Code: Select all

  messagePort = new SiMessagePort(SI_MESSAGE_PORT_DEVICE_ARDUINO_UNO, SI_MESSAGE_PORT_CHANNEL_A, new_message_callback);
an in AM use

Code: Select all

id = hw_message_port_add("ARDUINO_UNO_A", new_message)


they are then both matched.
First thing is to get the pico working with the work around for the com port VCP negotiation.
Try that and let me know. Once you can speak to it that is the first hurdle.
DONT try to edit anything in the messageport library please as it looks like you may have done, re-install it from download.
That can be sorted later once coms is established.

Joe
Joe. CISSP, MSc.

wendy
Posts: 46
Joined: Sun Aug 26, 2018 7:48 am
Contact:

Re: Raspberry PICO not working with message port, named hardware

#6 Post by wendy »

Hi Joe,

I have it working, just called it ARDUINO_NANO and AirManager listed it under devices as ARDUINO_NANO_D
OK that's good.

Connected an encoder to the PICO and like you said, open serial monitor and close. Startup AirManager and whoops it works with the LUA script to read the encoder.
So much ports and power in that little device, amazing !!!

I did not changed anything in the messageport lib as that will possibly break other things.

Thanks, and now waiting until this gets fixed !!!


Regards, Wendy

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Raspberry PICO not working with message port, named hardware

#7 Post by jph »

Excellent :)

If you are using a genuine PICO, then up the clock speed to 240Mhz,
then use a blink sketch or whatever with setup() and loop()

This will run on one core,
then create another setup1() and loop1()

and add a complex program here :mrgreen:

Now run it and you will see the blink program just runs happily away with no interrupts required and the second core program also just runs happily away.

Multi core ! :)

Also, check out the code optimiser for the pico

As an example I have some code here I wrote that uses 2 x 4067 multiplexers to scan a 256 key input matrix. It is pretty complex as it processes all the information for messaageport transfer and also does all the change of input checking and lots of boolean magic.

It runs, at 240 mhz single core, at about 2400 times a second for a complete 256 bit scan and all the math afterwards, that is a 16 x 16 matrix. That is pretty damn quick as owing to it being MUX driven you only can look at 1 input at a time, not a whole block.
Then, I can run the whole thing on the other core as well - with suitably named sections, and I am scanning TWO independent 256 input matrices at the same time on multiple cores with no loss of performance - all using just 8 pins !!! - yes, 8 total pins.
It is a killer processor a total game changer.

Enjoy and let me know how the experimenting goes.

:D
Joe
Joe. CISSP, MSc.

wendy
Posts: 46
Joined: Sun Aug 26, 2018 7:48 am
Contact:

Re: Raspberry PICO not working with message port, named hardware

#8 Post by wendy »

Hello Joe,

I sure will follow your advice. These are the first steps with the PICO but I have some pretty heavy stuff that he has to run. We will see how that turns out, but from what you are writing that should come ok.

You mention: Also, check out the code optimiser for the pico
Can you tell me where to find it or how to use ?

I'll keep you updated on my experiments.

Regards, Wendy

SimPassion
Posts: 5336
Joined: Thu Jul 27, 2017 12:22 am

Re: Raspberry PICO not working with message port, named hardware

#9 Post by SimPassion »

wendy wrote: Mon Sep 05, 2022 5:52 pm You mention: Also, check out the code optimiser for the pico
Can you tell me where to find it or how to use ?
Not sure if it should be used ... or not, as advised here :
https://hackaday.io/project/177082-rasp ... i-pico-sdk

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Raspberry PICO not working with message port, named hardware

#10 Post by jph »

wendy wrote: Mon Sep 05, 2022 5:52 pm Hello Joe,

I sure will follow your advice. These are the first steps with the PICO but I have some pretty heavy stuff that he has to run. We will see how that turns out, but from what you are writing that should come ok.

You mention: Also, check out the code optimiser for the pico
Can you tell me where to find it or how to use ?

I'll keep you updated on my experiments.

Regards, Wendy
It is in the tools option menu, I don't use PIO so have no idea where it is on that, I only use the stock IDE
Are you definitely running the Earle Philhower's PICO implementation ? - it is THE de-facto standard. https://github.com/earlephilhower/arduino-pico

The optimiser can be found here in the standard IDE - (see image below)

Oh, thanks Gilles, appreciated but luckily that link is is not relevant at it applies to another environment completely.

Here is the code for the experimental 4067 MUX 16 x 16 which you can use to test the speed of operation with the overclock and also the effectiveness of the optimiser as it will output its timing data on the serial monitor.
The code was an experiment to use two 50 cent mux units to scan 256 inputs. with 6 pins. It works well but It is just playing really.
For the actual cockpit for the 737 I am using Semtech SX1509 programmable I/O units, amongst others as well as neopixels. The SX1509s are truly amazing - as are neopixels for annunciators . So flexible. I have just ordered a batch of 25 x 1509s.

Anyway, you can experiment with the code for effects of overclock and optimise. I will develop it further one day as it has it's uses. It is something to add a load to a single core. - when you have it running and outputting on the serial port add the blink sketch to core two :D

Code: Select all

/*
******************************************************************************************************
        1st run at 256 input 16 x 16 bit multiplexed matrix
     Custom code - Joe Hanley 2022 - JPH - Air Manager forums
******************************************************************************************************
*/
// includes
// defines

// constants
// our mux control pins for the 16:1 CD4067 mux/decoders
//const uint8_t CD4067_COL_S0 = 22;
//const uint8_t CD4067_COL_S1 = 24;
//const uint8_t CD4067_COL_S2 = 26;
//const uint8_t CD4067_COL_S3 = 28;
//const uint8_t CD4067_COL_IO = 30;
//const uint8_t CD4067_ROW_S0 = 32;
//const uint8_t CD4067_ROW_S1 = 34;
//const uint8_t CD4067_ROW_S2 = 36;
//const uint8_t CD4067_ROW_S3 = 38;
//const uint8_t CD4067_ROW_IO = 40;

const uint8_t CD4067_COL_S0 = 4;
const uint8_t CD4067_COL_S1 = 5;
const uint8_t CD4067_COL_S2 = 5;
const uint8_t CD4067_COL_S3 = 7;

const uint8_t CD4067_COL_IO = 8;

const uint8_t CD4067_ROW_S0 = 9;
const uint8_t CD4067_ROW_S1 = 10;
const uint8_t CD4067_ROW_S2 = 11;
const uint8_t CD4067_ROW_S3 = 12;

const uint8_t CD4067_ROW_IO = 13;


const uint8_t CD4067_TRUTH_TABLE[16][4] = {
  // s0, s1, s2, s3     channel
  {0,  0,  0,  0}, // 0
  {1,  0,  0,  0}, // 1
  {0,  1,  0,  0}, // 2
  {1,  1,  0,  0}, // 3
  {0,  0,  1,  0}, // 4
  {1,  0,  1,  0}, // 5
  {0,  1,  1,  0}, // 6
  {1,  1,  1,  0}, // 7
  {0,  0,  0,  1}, // 8
  {1,  0,  0,  1}, // 9
  {0,  1,  0,  1}, // 10
  {1,  1,  0,  1}, // 11
  {0,  0,  1,  1}, // 12
  {1,  0,  1,  1}, // 13
  {0,  1,  1,  1}, // 14
  {1,  1,  1,  1}  // 15
};


// variables

// our arrays for binary data. 16 bits for incoming to start with as that is the width of the matrix, then push to 32 bit for messagePort transfer.
uint16_t matrixRead16[16];     // 16 x 16 bit uint16_t for storage of the complete 256 bits per full matrix read.
uint32_t matrixRead32Last[8];  // 16 x 16 bit uint16_t for LAST storage of the complete 256 bits per full matrix read.
uint32_t matrixRead32[8];      // pack the 16 bit reads for transport to 8 32 bits where 32[0]  is [1] and [0] of 16
bool     isNewMatrix[16];      // flags indicating that a 16 bit section has changed

//****************************************************************************************************

void setup() {                         //  setup: run once
  Serial.begin(115200);

  pinMode(CD4067_COL_S0, OUTPUT);
  pinMode(CD4067_COL_S1, OUTPUT);
  pinMode(CD4067_COL_S2, OUTPUT);
  pinMode(CD4067_COL_S3, OUTPUT);
  pinMode(CD4067_COL_IO, INPUT);   // this is where we read the data bit on the scan
  pinMode(CD4067_ROW_S0, OUTPUT);
  pinMode(CD4067_ROW_S1, OUTPUT);
  pinMode(CD4067_ROW_S2, OUTPUT);
  pinMode(CD4067_ROW_S3, OUTPUT);
  pinMode(CD4067_ROW_IO, OUTPUT); // this is always HIGH, it is the ROW logic 1 driver state. All other rows are pulled down by 10k resistors.

  digitalWrite(CD4067_ROW_IO, HIGH);
}                                      //    setup end

void setup1() { // core 2
   pinMode (LED_BUILTIN, OUTPUT);
}

void loop1() { // core 2
  digitalWrite ( LED_BUILTIN,HIGH );
  delay(1000);
  digitalWrite ( LED_BUILTIN,LOW );
  delay(1000);
}
//****************************************************************************************************

void loop() {                          // main program loop

  uint8_t x = 0;
  uint32_t test = 0;
  uint32_t count = 0;
  // was 2268 test 1
  //
  
  float now1 = millis()+1000;
  while (millis() < now1) {
  //for (uint32_t test = 0; test <= 5000; test++ ) {
    if (scanInputMatrix()){      // scan returned a matrixNew flag set so we have new data
      sendMatrixToMessagePort(); // need to check serial port buffers etc
    } 
    count++;
  }

  //float now2 = millis();
  //delay(1000);
  Serial.print(count);
  Serial.print(" scans completed in ");
  //Serial.print((now2 - now1) / 1000);
  Serial.println(" 1 Seconds");




}                                      // main loop end

/*
******************************************************************************************************
                                            Subroutines
******************************************************************************************************
*/
void sendMatrixToMessagePort() {
  // stuff appropriate data to MP - minimise transfer
  // now we have 8 matrixRead32[] units of the array which contain - for example - matrixRead32[0] is made up of matrixRead15[0] in the low word and matrixRead16[1] in the highword etc
  // we also have flags for the isNewMatrix[x] which are the 16 original array elemenets
}



bool scanInputMatrix() {
  //  Serial.println("We got to scanInputMatrix ! ");
  uint8_t tempRead = 0;
  uint8_t x = 0;
  bool matrixNew = false;
  
  
  for ( x = 0; x < 8; x++ ) {        // clear all previous values
    matrixRead32[x] = 0;                   // clear all cells ready for read
    isNewMatrix[x]  = false;                // clear all 'new reading' flags
  }

  for ( x = 0; x <= 15; x++ ) {        // step our matrix
    CD4067setColumn(x);                      // set the column number that the mux is open on
    for (uint8_t y = 0; y <= 15; y++) {      // now we will step through all 16 rows and read the col value for that row,
      CD4067setRow(y);                       // ROW IO is always a HIGH OUTPUT - this is the driver, we read the COL IO !
      // read in value
      //if ( x != 0) matrixRead16[x] = matrixRead16[x] << 1;     // shift left 1 place - but not on the very first time !
      matrixRead16[x] = matrixRead16[x] << 1;                    // shift left 1 place - but not on the very first time ! // IF the var is EMPTY to start with this wont be an issue.
      //        tempRead = digitalRead(CD4067_COL_IO);           // now contains the value from that read = 0 or 1 only
      //        matrixRead16[x] = matrixRead16[x] + tempRead;    // place value in bit 0
      tempRead = digitalRead(CD4067_COL_IO);                     // now contains the value from that read = 0 or 1 only
      bitWrite(matrixRead16[x], 0, tempRead);
    }
  }
//   now convert to 8 x 32 bit
//   convert uint16_t to uint32_t
  for ( x = 0; x < 8; x++) {                              // stuff the values, upper and lower into matrixRead32 from matrixRead16
    matrixRead32[x] = matrixRead16[x + 1];                // stuff the lower 16 bits
    matrixRead32[x] = matrixRead32[x] << 16;              // shift these left into the higher 16 bits
    matrixRead32[x] = matrixRead32[x] + matrixRead16[x];  // now matrixRead32[x] has the upper 16 bits stuffed with matrixRead[1] and lower with [0], and same for all others
  }

//   compare to old values from last scan and update where needed
  for ( x = 0; x < 8; x++) {                              // loop through our 8 x uint32_t arrays
    if (matrixRead32[x] != matrixRead32Last[x]) {         // we will store ANY changes and set the flag if changed
      matrixRead32Last[x] = matrixRead32[x];              // store our changed values in matrixRead32Last[]
      isNewMatrix[x] = true;                              // our individual 32 bit int flags to identify which ones have changed to allow selective sending to messagePort                                                          /
      matrixNew = true;
    }
  }
  return (matrixNew);
}



void CD4067setColumn(uint8_t channel)
{
  digitalWrite(CD4067_COL_S0, CD4067_TRUTH_TABLE[channel][0]);
  digitalWrite(CD4067_COL_S1, CD4067_TRUTH_TABLE[channel][1]);
  digitalWrite(CD4067_COL_S2, CD4067_TRUTH_TABLE[channel][2]);
  digitalWrite(CD4067_COL_S3, CD4067_TRUTH_TABLE[channel][3]);
}

void CD4067setRow(uint8_t channel)
{
  digitalWrite(CD4067_ROW_S0, CD4067_TRUTH_TABLE[channel][0]);
  digitalWrite(CD4067_ROW_S1, CD4067_TRUTH_TABLE[channel][1]);
  digitalWrite(CD4067_ROW_S2, CD4067_TRUTH_TABLE[channel][2]);
  digitalWrite(CD4067_ROW_S3, CD4067_TRUTH_TABLE[channel][3]);
}
Optimiser -
optimisepico.jpg
Joe
Last edited by jph on Tue Sep 06, 2022 8:45 am, edited 1 time in total.
Joe. CISSP, MSc.

Post Reply