volts.py output problem

The more technical aspects of Spirit, and carry-over discussion from Kickstarter updates.
Kevin
Posts: 176
Joined: Tue Jul 28, 2015 12:56 am

Re: volts.py output problem

Postby Kevin » Sun Feb 18, 2018 6:35 pm

This is helpful. I can't dig into it right away but it's a start.

Let's try this now.....

Load up a sketch on the Arduino, and have it run the function PIC_ReadPower() in a loop with a delay of maybe 2 seconds between calls. Have that sketch print powerVoltage variable to the serial monitor on the loops. You should get good data on this and you should see it change somewhat over time. (you can also echo powerCurrent at the same time, it is updated by the same function and powerCurrent should be bouncing around a bit).

Then try to sniff the same trafic with the Arduino making the call. We should be getting the same response packet as it's basically doing the same thing as when the Pi calls it.

Also if anyone else reading this is able to get good data from the volts.py script please let me know. So strange several of you having this problem but I can't recreate it here.

Thanks!

gpvillamil
Posts: 75
Joined: Fri Jan 26, 2018 5:03 pm

Re: volts.py output problem

Postby gpvillamil » Mon Feb 19, 2018 11:49 pm

I followed your software install instructions exactly, and I am also getting the volts.py output problem. I get the same response from rangefinder.py, lightsense_surface.py and lightsense_ambient.py.

motors_spinleft.py and motors.py work correctly, when the appropriate Arduino baseSketch is running.

Of the demo code, the pixels_autofade_wing.py demo works well. The servo_shakehead.py works too, though with quite a delay.

I do notice the system is running much more slowly. I am connecting over RealVNC. top shows python consuming 16% CPU pretty much all the time. (Edit: whatever was causing this seems to have sorted itself out after a reboot, python is now 1% of CPU).

I was starting to see some very strange behavior with Arduino sketches too - they seemed to be running at twice their speed - but that seems to have sorted itself out too.

Kevin wrote:I know the I2C bus can be run at different speeds. I wonder if somehow my unit is at a different speed. Does anyone know off hand how to configure this?

Also, some of you started setting up your Pi units before I gave my own setup instructions. I wonder if maybe I did something different when installing the smbus package or one of the related packages?

-Kevin
Last edited by gpvillamil on Tue Feb 20, 2018 1:07 am, edited 1 time in total.

acojon
Posts: 6
Joined: Sat Feb 17, 2018 12:39 am

Re: volts.py output problem

Postby acojon » Tue Feb 20, 2018 12:57 am

I sat down to run the process by using Arduino instead, to see what I could learn.

Sometimes I do pretty badly with various Arduino things...

I hard a hard time figuring out how I should be storing the value returned from PIC_ReadPower(), I eventually gave up and started testing the serial monitor, and discovered that I'm not getting good data back, I'm not quite sure what I'm doing wrong.

Here is the sketch I wrote and uploaded to the rover:

Code: Select all

#include "Hardware.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Hello, starting.");

  // ************ THE SETUP ITEMS BELOW SHOULD GENERALLY BE USED FOR ALL SPIRIT SKETCHES **************

  hardwareBegin();                    //initialize Spirit's Arduino processor to work with his circuitry
  SPI_Reset();                        //resets and turns on the SPI port
  setAllPixelsRGB(0, 0, 0);           //turn off all pixels before we get started
  playStartChirp();                   //Play startup chirp and blink eyes
  servoCenters();                     //Place all servos back in default position
}

void loop() {
  // put your main code here, to run repeatedly:

  PIC_ReadPower();
  Serial.print("Power: ");
//  Serial.println(PIC_ReadPower());
//  Serial.println(power);
  delay(2000);
}


And here is the data I got back on the Serial Monitor:

Code: Select all

⸮⸮⸮;⸮⸮⸮C⸮⸮⸮⸮⸮


Which doesn't look too helpful :) I checked that the monitor is set to 9600, which matches the value from the sketch.

I'm obviously missing something, but I'm not quite sure what that is. Does anyone see what I'm doing wrong?

I went ahead and connected up the Bus Pirate to see if I could capture the I2C traffic:

When running it at 100mhz, here is the output I got:

Code: Select all

[0x64+][[0x54+0xE6+0x81+0xC3+]


And then I switched it to 400mhz (Which doesn't work very well) and I got this output:

Code: Select all

[0x48+][]][0x85+0x0E+0x6A+0x2B-]


I'm not sure what the speed is for the I2C communication when the Arduino is communicating on the bus, so I may not have caught the data with the right speed.

And since I couldn't make the serial monitor work, I'm not sure what values were captured :)

And finally, I looked through the Python code for various functions that were using I2C to communicate, and when I ran those commands, I would get the same error back as I would with volts.py.

Bastian
Posts: 21
Joined: Sun Oct 22, 2017 5:30 pm

Re: volts.py output problem

Postby Bastian » Tue Feb 20, 2018 4:35 pm

In my case the Comm led doesn't blink. AS to the exact content of the message sen aand recied, with a small additiong in spirit:core:

┌────────────────────────────────────────────────────────────────────┐
│ • MobaXterm 10.4 • │
│────────────────────────────────────────────────────────────────────┘
Linux Rpi3bV1-2 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l

(rover) pi@Rpi3bV1-2:~/rover/democode $ python volts.py
Battery Voltage: i2C request = 50 21 5 (bus address, register, length)
i2C repy= [255, 255, 255, 255, 255]
0
i2C request = 50 21 5
i2C repy= [255, 255, 255, 255, 255]
0
i2C request = 50 21 5
i2C repy= [255, 255, 255, 255, 255]
0
(rover) pi@Rpi3bV1-2:~/rover/democode $

I've also tried different I2C-delay's and different I2C-speeds. All without any effect.

I wonder if the problem lies in the RPi using the I2C bus (which is not Rpi's strongest point overall)?? In my own projects I use ARduino I2C to send req's/revieve/data to/from sensors and have Arduino and RPI communicate through serial. (RX-tX/usb, spi, whatever) That alway works flawless up to 0.5 Mhz. Arduino and RPi using the same bus, seems asking for trouble to me.Halas I don't have time to recode the base sketch and helper files to try it out.

gpvillamil
Posts: 75
Joined: Fri Jan 26, 2018 5:03 pm

Re: volts.py output problem

Postby gpvillamil » Tue Feb 20, 2018 6:25 pm

Yes, this makes a lot of sense. Defining a protocol for the RPi to talk to Arduino over SPI seems like an architecturally sound way to do it. Kevin has given us all the information we need to implement this, in a dedicated post. Then we can get rid of the pixelserver.

I saw some VERY strange behavior on the Arduino after I first installed all the Python software. (Arduino sketches that had previously worked went crazy, the demo sketch seemed to run much faster AND top on the RPi showed really high CPU utilization for Python process.) I think the pixelserver had gone rogue and was saturating the I2C bus.

Bastian wrote:I wonder if the problem lies in the RPi using the I2C bus (which is not Rpi's strongest point overall)?? In my own projects I use ARduino I2C to send req's/revieve/data to/from sensors and have Arduino and RPI communicate through serial. (RX-tX/usb, spi, whatever) That alway works flawless up to 0.5 Mhz. Arduino and RPi using the same bus, seems asking for trouble to me.Halas I don't have time to recode the base sketch and helper files to try it out.

Kevin
Posts: 176
Joined: Tue Jul 28, 2015 12:56 am

Re: volts.py output problem

Postby Kevin » Tue Feb 20, 2018 6:42 pm

Okay thanks for the feedback.

Let's try something else....

We have a few pauses we can play with. We already tried setting the "i2c_process_delay(15)" in the main script and found it had no effect. This sets a response delay within the PIC itself.

There are two other delays that are inserted on the Pi side. Have a look at the spirit_core.py file.

The power_voltage function will return a cached value if it is called more quickly than the PIC is updating it's own local value. We are seeing the I2C Wrong Register error, so that tells me we're getting past this part and we are indeed attempting a bus transaction to read the value.

power_voltage calls PIC_ReadPower. You can see this function in this section of the file:
def PIC_ReadPower(self):

There is a line in that function "pause = 0.0016" Let's try changing that pause to some different values longer or shorter. This "pause" value is going to be passed to the actual function that does the read (it's pretty easy to see how the function works by just reading over it).

Then look at the actual function that does the bus work. It is near the bottom of the file and starts like this:
def i2cRead(self,register,length,pause):

Study this function - you can see where the error message is being printed from in this message. We can add an additional pause each time the function is called by changing the hard coded value of "i2c_read_extra_pause", which is one of the variables set up in the list just preceding this function. It is presently set to zero, but if you change this "i2c_read_extra_pause" value, it should insert an additional delay of the given number in microseconds.

If the bus on the Pi on your units is behaving more quickly than what I'm running here, it is possible the transaction is happening too quickly, and by changing the delay numbers above, we can force a longer delay here, which may solve our problem.



A couple quick thoughts on the notes above....

It shouldn't matter that the Arduino and the Raspberry Pi are sharing the same I2C bus. I2C is designed to be shared. As long as you don't have both devices trying to run a lot of traffic all at once, it should be okay. (Under the I2C specification, it shouldn't matter, but due to the hardware bug in the Pi, it causes problems).

Speed issues with the Arduino - this could happen by selecting the wrong Board in the Arduino software as it will compile for a different clock speed. The Arduino we use is running at 8MHz, where the standard UNO uses the same chip but running at 16MHz.

If the "shake head" python example works, this is a good sign because this also uses the I2C bus, except it is not requesting a response from the PIC, but rather is telling the PIC to set a value.

Off top of my head, when a query is made, the master (in this case the Pi) sends a short packet to the PIC telling it what "register" it wants to read. A handler on the PIC goes and gets the voltage or whatever then populates it into the reply buffer. A short time later the Pi tries to call the PIC again in "read" mode, and the PIC then takes control of the bus and sends the reply back to the Pi.

It looks like we're getting all 255's for response values. It sounds to me like something isn't being timed correctly.

I don't think anything is hanging the bus, because I2C is very picky about the two signal lines going up and down in very specific patterns. If one of those lines is being held by the other side, the opposite side will refuse to do anything and you should get a hung program or some other kind of error. One of you did a data grab above, and I am seeing the register numbers change, so it looks like the bus is still physically functioning, it's just maybe something is out of timing. On the volts query, it should only take that PIC a couple microseconds to populate the outgoing packet, and it does respond properly when the Arduino calls it (from what I'm understanding from the above anyway).

One of you mentioned the shake head works, but seems delayed. Can you expand on that? Is it more than the expected delay between movements, or does it just take a long time to start running after the terminal command is issued?

I am hand building a unit for another person right now using one of the backer kits. When I complete that, I'll go through the setup steps I listed again from a fresh card and see if I'm able to repeat the issue. If I can, I will at least be able to look on the scope and try to figure out what is going on.

It would be an ugly work-around but very worst case, we could have the Arduino do the comms with the PIC then use SPI between the Arduino and Pi to relay the data (and we know this process works because the motors functions work).

I tested every board, but I did test them all with a single Pi, and as far as I remember, that Pi came from the same batch I sent to the backers. So if it's something that can't be worked around, it would be some freak thing that the 2 robots I have as prototypes and the 1 unit I have as a test fixture all work fine, and the test fixture works fine with all the boards that were shipped, but somehow all the Pi's that went out (but not the ones I'm testing with) are having some issue. I find that unlikely so I'm pretty sure we'll get this solved at some point.

gpvillamil
Posts: 75
Joined: Fri Jan 26, 2018 5:03 pm

Re: volts.py output problem

Postby gpvillamil » Wed Feb 21, 2018 12:56 am

Regarding this:

acojon wrote:I hard a hard time figuring out how I should be storing the value returned from PIC_ReadPower(), I eventually gave up and started testing the serial monitor, and discovered that I'm not getting good data back, I'm not quite sure what I'm doing wrong.


You don't use the value returned by PIC_ReadPower() directly. Whenever that function is called, it populates two global variables, powerVoltage and powerCurrent. Use those.

Here's a sketch that will return current and voltage (and put on a pretty light show):

Code: Select all


/*

  Spirit Rover Robot
  Spirit Rainblow Chase

  Creates a simple "rainbow chase" effect on the rover LEDs

  Significant portions of this code written by
  Dustin Soodak for Plum Geek LLC. Some portions
  contributed by Kevin King.
  Portions from other open source projects where noted.
  This code is licensed under:
  Creative Commons Attribution-ShareAlike 2.0 Generic (CC BY-SA 2.0)
  https://creativecommons.org/licenses/by-sa/2.0/
  Visit http://www.plumgeek.com for PiSpirit information.
  Visit http://www.arduino.cc to learn about the Arduino.

*/

#include "Hardware.h"

struct color {
  byte red;
  byte green;
  byte blue;
};

int theBrightness = 25;

void setup() {

  // ************ THE SETUP ITEMS BELOW SHOULD GENERALLY BE USED FOR ALL SPIRIT SKETCHES **************

  hardwareBegin();                    //initialize Spirit's Arduino processor to work with his circuitry
  SPI_Reset();                        //resets and turns on the SPI port
  playStartChirp();                   //Play startup chirp and blink eyes
  servoCenters();                     //Place all servos back in default position

  // ************ THE SETUP ITEMS BELOW CAN BE CUSTOMIZED FOR YOUR SPECIFIC SPIRIT SKETCH **************


  // add your own setup code here

  Serial.begin(57600);
}


void loop() {

  // add your own loop code here

  PIC_ReadPower();
  Serial.print("Current: ");
  Serial.print(powerCurrent);
  Serial.print(" Voltage: ");
  Serial.println(powerVoltage);


  for (int i = 0; i <= 255; i++) {
    for (int j = 0; j <= 26; j++) {
      struct color myColor = colorWheel((i * 1 + j * 8) % 255, theBrightness);
      setPixelRGB(j, myColor.red, myColor.green, myColor.blue);
    }
    RefreshPixels();
    delay(0);
  }

} // end of loop() function

struct color colorWheel(byte WheelPos, byte brightness) {
  struct color theColor;
  if (WheelPos < 85) {
    theColor.red  = map(255 - WheelPos * 3, 0, 255, 0, brightness);
    theColor.green = 0;
    theColor.blue = map(WheelPos * 3, 0, 255, 0, brightness);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    theColor.red = 0;
    theColor.green = map(WheelPos * 3, 0, 255, 0, brightness);
    theColor.blue = map(255 - WheelPos * 3, 0, 255, 0, brightness);
  } else {
    WheelPos -= 170;
    theColor.red = map(WheelPos * 3, 0, 255, 0, brightness);
    theColor.green = map(255 - WheelPos * 3, 0, 255, 0, brightness);
    theColor.blue = 0;
  }
  return theColor;
}

gpvillamil
Posts: 75
Joined: Fri Jan 26, 2018 5:03 pm

Re: volts.py output problem

Postby gpvillamil » Wed Feb 21, 2018 1:12 am

Kevin, I wonder if this might have something to do with the Raspberry Pi firmware (that was updated with rpi-update, NOT apt-get).

I noticed the build of Raspbian that shipped was out of date, so when I did apt-get dist-upgrade I got the latest Jessie build (with Pixel GUI, VNC, etc). I believe this version no longer requires rpi-update, it will update firmware by itself to the latest STABLE build, on the first partition of the SD Card.

So perhaps our firmware is out of sync? Could you have updated to a more recent firmware, more current than the latest?

I am on firmware 4.9.35-v7+, and rpi-update proposes updating to 4.14.y

Can you check which one you have?

acojon
Posts: 6
Joined: Sat Feb 17, 2018 12:39 am

Re: volts.py output problem

Postby acojon » Wed Feb 21, 2018 1:38 am

Hi gpvilamil,

That explanation makes sense, thank you. I uploaded the code uploaded to the Spirit Rover. I switched my serial monitor over to 57600 baud, and this is what I got on the serial monitor:

Code: Select all

⸮⸮⸮⸮⸮⸮⸮


All of the lights on my Rover turned on, and I'm guessing the R G B values maxed out, it was quite bright, but no animations :) The code looks pretty straight forward, so I'm not sure why it's behaving badly on my Rover.

I set the board to Arduino Pro or Arudino Pro Mini, and the Processor to ATmega328P (5v 16mhz)

I'm obviously doing something wrong, but not yet sure what that is :)

Thank you for the help!

Kevin
Posts: 176
Joined: Tue Jul 28, 2015 12:56 am

Re: volts.py output problem

Postby Kevin » Wed Feb 21, 2018 2:39 am

What commands should I run in terminal to check versions?

Actually it may be a good idea for me to check versions of all kinds of stuff. If you can maybe make a list of commands, I can run and post the results. I'm thinking anything relevant - the Pi firmware, Linux version, etc. Also the SMBUS package I believe is important. Let me know and I'll give it a shot. I don't think I did anything to my unit other than what I listed in the guide but it's certainly possible something is different.

I can do lists of packages installed, etc, just let me know what to run.

Thanks!


Who is online

Users browsing this forum: No registered users and 1 guest