robot project, where to start?

04 Jan 2018

i'm building a rocker bogie type robot. 6 wheels (6 12V drive motors with encoders, 20A max if stalled, probably will run much much less maybe 200w total) 6 servos (all 6 wheels can be steered) 2 shorai batteries, 1.5 lbs each, 14 Amp hours each 3 dual motor controllers, 3 12V switching regulators 5V switching regulator 3.3V regulator STM32F746ZG as the mini-brain to control the motors, also to read data from MPU-9250 for acceleration/ gps / compass

the STM32 will send data to / receive commands from a raspberry pi (onboard) the pi will do wifi, data lookups (robot will be required to query google when commanded haha)

my needs are to program the STM32 to monitor the wheels / control the motors, monitor MPU-9250 for data, also some other sensors - temp, sonar, infrared, possibly LiDAR later for SLAM mapping.

in order to get started with the STM32 i can program and set up from my Mac or my PC for development platform.

i want REAL time action... the robot does not have to stop to change course. if the sensors pick up and obstacle, the Pi will send emergency steering commands to the STM32, the STM32 will make changes on-the-fly via PWM

so i need to know how to program motor control, sensor readings, sending/receiving data from the master

from the community, i want to know the best dev platform to use for the STM32? which projects here on mbed would you recommend for study to learn: 1. motor control, using proper interrupt handling 2. servo control 3. sensor monitoring 4. communication & command exchange with master

just for your interest something cool i'm implementing is a self-charging routine. the robot will back into a dock; the dock will have 3 magsafe 2 connectors (5 pins each) that are found on mac laptops. the robot will have proper position, and as soon as the magsafe connectors get within about 1/8 inch they will "pop" into place. the robot will activate the shorai chargers via radio command or via the 15th pin. the shorai batteries use 7 pins each for proper charging (thus i need 14 pins, the last pin i can use to activate the chargers.)

13 Jan 2018

so far, i have crossed one major hurdle. i can now send commands from the raspberry to the Nucleo-F746ZG

they are wired with SPI

i'm using SPI_B pins on the Nucleo for my model it's CN7 pins

CN7 #8 GND  goes to the Raspberry  Pin #20 GND
CN7 #13  -- SPI_B_MOSI  PB_5 goes to Raspberry #19 MOSI
CN7 #15 -- SPI_B_SCK PB_3 goes to Raspberry #23 SCLK
CN7 #17 -- SPI_B_NSS PA_4 goes to Raspberry #24 CE0
CN #19 -- SPI_B_MISO PB_4 goes to Raspberry #21 MISO

the code on the Nucleo-F746ZG, then the code on the Raspberry:

#include "mbed.h"
 SPISlave device(PB_5, PB_4, PB_3, PA_4); // mosi, miso, sclk, ssel
 // Green LED
DigitalOut led1(LED1);
// Blue LED
DigitalOut led2(LED2);
// Red LED
DigitalOut led3(LED3); 

void select_led(int l)
{
        if (l==0) {
                led1 = false;
                led2 = false;
                led3 = false;
        }
        else if (l==1) {
                led1 = true;
                led2 = false;
                led3 = false;
        }
        else if (l==2) {
                led1 = false;
                led2 = true;
                led3 = false;
        }
        else if (l==3) {
                led1 = false;
                led2 = false;
                led3 = true;
        }
        else if (l==-1) {
                led1 = true;
                led2 = true;
                led3 = true;
        }
} 

int main() {
 
    int t=2;
    int k=0;

    device.format(8,3);        // Setup:  bit data, high steady state clock, 2nd edge capture
    device.frequency(12500000); // 12.5MHz
 
    int reply = 99;
    device.reply(reply);              // Prime SPI with first reply
    device.reply(reply);              // Prime SPI with first reply, again
 
    while (1) {
        k=(t-2);
        select_led(k);
        wait(0.0001);
        t=(t%5)+1;
        if (device.receive()) {
            int valueFromMaster = device.read();
            device.reply(++reply);              // Prime SPI with next reply
        }
    }
}

the code on the Raspberry: (originally tested on 1Mhz, but works perfect at 12.5Mhz; i haven't decided what speed yet to stick with because i think more Mhz = more power consumption)

it uses a library by Mike McCauley which can be found on his own website, it's linked off the main raspberry pi org website

// spin.c
//
// Example program for bcm2835 library
// Shows how to interface with SPI to transfer a number of bytes to and from an SPI device
//
// After installing bcm2835, you can build this 
// with something like:
// gcc -o spin spin.c -l bcm2835
// sudo ./spin
//
// Or you can test it before installing with:
// gcc -o spin -I ../../src ../../src/bcm2835.c spin.c
// sudo ./spin
//
// Author: Mike McCauley
// Copyright (C) 2012 Mike McCauley
// $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $

#include <bcm2835.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    // If you call this, it will not actually access the GPIO
// Use for testing
//        bcm2835_set_debug(1);
    
    if (!bcm2835_init())
    {
      printf("bcm2835_init failed. Are you running as root??\n");
      return 1;
    }

    if (!bcm2835_spi_begin())
    {
      printf("bcm2835_spi_begin failed. Are you running as root??\n");
      return 1;
    }
    bcm2835_spi_begin();
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE3);                   // The default
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_32); // The default
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default
    
    // Send a some bytes to the slave and simultaneously read 
    // some bytes back from the slave
    // Most SPI devices expect one or 2 bytes of command, after which they will send back
    // some data. In such a case you will have the command bytes first in the buffer,
    // followed by as many 0 bytes as you expect returned data bytes. After the transfer, you 
    // Can the read the reply bytes from the buffer.
    // If you tie MISO to MOSI, you should read back what was sent.
while (1)
{    
    char buf[] = { 0x01, 0x02, 0x11, 0x33 }; // Data to send
    bcm2835_spi_transfern(buf, sizeof(buf));
    // buf will now be filled with the data that was read from the slave
    printf("Read from SPI: %02X  %02X  %02X  %02X \n", buf[0], buf[1], buf[2], buf[3]);
}    
    bcm2835_spi_end();
    bcm2835_close();

    return 0;