Teensy 4.1 NativeEthernet lib interfering with I2C?

mick

Active member
Hi there,

I'm using a Teensy 4.1 combined with this PWM driver by Adafruit

https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all

The issue I'm experiencing, is that when I try to use the NativeEthernet library combined with the PWMServoDriver library, the moment I call Ethernet.begin(); one or two seconds later the PWM driver stops responding

Below is the example patch I'm using, its basically just the pwmtest example from the PWMServoDriver library and the UDPSendReceiveString example from the NativeEthernet library.

Does anyone know why this might be happening? Are there any reserved pins or other things that are interfering? I'm running the example on a custom PCB, I'll try and setup the same experiment with just a teensy and one of Adafruit's boards to see if it makes a difference, I'm quite puzzled though, since as far as I understand the PWM library used I2C, and the NativeEthernet library uses SPI, correct?

Code:
/***************************************************
  This is an example for our Adafruit 16-channel PWM & Servo driver
  PWM test - this will drive 16 PWMs in a 'wave'

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815

  These drivers use I2C to communicate, 2 pins are required to
  interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 2, 177);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";        // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

#define PWM_NUM 8

Adafruit_PWMServoDriver pwm[] = {  (0x40), (0x41), (0x42), (0x43), (0x44), (0x45), (0x46), (0x47)  };

// called this way, it uses the default address 0x40
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);

void setup() {
  Serial.begin(9600);
  Serial.println("16 channel PWM test!");

  // start the Ethernet
  Ethernet.begin(mac, ip);

  for (uint8_t p = 0; p < PWM_NUM; p++) {
    pwm[p].begin();

    /*
      In theory the internal oscillator (clock) is 25MHz but it really isn't
      that precise. You can 'calibrate' this by tweaking this number until
      you get the PWM update frequency you're expecting!
      The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
      is used for calculating things like writeMicroseconds()
      Analog servos run at ~50 Hz updates, It is importaint to use an
      oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
      1) Attach the oscilloscope to one of the PWM signal pins and ground on
        the I2C PCA9685 chip you are setting the value for.
      2) Adjust setOscillatorFrequency() until the PWM update frequency is the
        expected value (50Hz for most ESCs)
      Setting the value here is specific to each individual I2C PCA9685 chip and
      affects the calculations for the PWM update frequency.
      Failure to correctly set the int.osc value will cause unexpected PWM results
    */
    pwm[p].setOscillatorFrequency(27000000);
    pwm[p].setPWMFreq(1600);  // This is the maximum PWM frequency
  }




  // if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode
  // some i2c devices dont like this so much so if you're sharing the bus, watch
  // out for this!
  Wire.setClock(400000);
}

void loop() {

  float b = map(sin(millis() * 0.01), -1, 1, 0, 1);
  int t = b * 4095;

  for (uint8_t c = 0; c < PWM_NUM; c++) {
    for(uint8_t p = 0; p < 16; p++) {
      pwm[c].setPWM(p, 0, t );      
    }
  }
}
 
Small update, I've just verified the same behaviour running one of Adafruit's original boards in connection with a Teensy 4.1 on a breadboard. The issue must be somewhere internal (not related to my PCB).


After a bit more testing it seems to be related to the amount of PWM chips I have. When PWM_NUM is 4, things are fine, but going up to PWM_NUM 5 makes the PWM stop responding. I've also added a blinking LED, which shows me that the sketch itself is still running.

Could it be that I need to resort to threading or something? All I can deduct atm is that having more than 4 PWM chips combined with running Ethernet.begin() is too much somewhere.

Code:
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";        // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// 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

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#define PWM_NUM 5
Adafruit_PWMServoDriver pwm[] = {  (0x40), (0x41), (0x42), (0x43), (0x44), (0x45), (0x46), (0x47)  };


void setup() {

  pinMode(ledPin, OUTPUT);

  for (uint8_t p = 0; p < PWM_NUM; p++) {
    pwm[p].begin();
    pwm[p].setOscillatorFrequency(27000000);
    pwm[p].setPWMFreq(1600);  // This is the maximum PWM frequency
  }
  Wire.setClock(400000);

  // start the Ethernet
  Ethernet.begin(mac, ip);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("hi!");

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start UDP
  Udp.begin(localPort);
}

void loop() {

  float b = map(sin(millis() * 0.01), -1, 1, 0, 1);
  int t = b * 4095;

  for (uint8_t c = 0; c < PWM_NUM; c++) {
    for(uint8_t p = 0; p < 16; p++) {
      pwm[c].setPWM(p, 0, t );      
    }
  }


  
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  //delay(10);

  unsigned long currentMillis = millis();

  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);
  }
}
 
Last edited:
Could it be related to PWM chips that aren't connected? Why would this kill the I2C connection after a few seconds? And also why only in junction with Ethernet.begin() ?

Update: By now I'm pretty certain it only happens when I'm trying to send data to PWM chips that don't sit on the I2C bus... no clue why this is only an issue when I'm also using ethernet though.
 
Last edited:
Hi @BriComp,

I meant that it only happens when I call Ethernet.begin() in the setup.

By now I know a bit more. Basically its an issue when in the code I try to control more PWM chips than I have connected. Somehow this is only an issue when I'm also trying to use ethernet. Happy though to see if I call the amount of PWM chips actually connected that it works.
 
ah, yes, apologies, non-native speaker here.

By now I've sorted out most of the issues. Main learning is that the PWM chips need to be attached if they are addressed in the firmware.
 
I noticed your question wasn’t answered. NativeEthernet does not use SPI.

I’m wondering if you’d still see issues with the QNEthernet library. Do you feel like trying that out? See the examples for several ways to use the library.
 
I'm seeing this issue still isn't resolved, Encountered the same, Adafruit & Ethernet on Teensy 4.1
Each verified working, but together the I2C fails to read.
 
OK, found something a little weird
SparkFun code:
//We expect caller to begin their I2C port, with the speed of their choice external to the library
//But if they forget, we start the hardware here.
//_i2cPort->begin();
Added Wire.begin and it works.
 
I'm running the code in msg #2 on a Teensy 4.1 with ethernet connected, but no I2C servo motor boards.

It prints "hi!" in the serial monitor and the LED blinks slowly.

Not sure what software I'm supposed to run elsewhere on my network to send the UDP packet this code expects to receive?

Do I need to have 5 of those Adafruit servo boards to reproduce this problem?
 
@mick - I am going to assume that you have the vcc on those boards hooked up to 3.3v and not 5v's?

I don;t have one of the pwm boards that you linked but do have a motor driver board (https://www.adafruit.com/product/1438) that I uses I2C to control motors and servos that I have used with internet without issue. The only mod I made to the board was switching it to use 3.3v for the logic and not 5v.

EDIT: guess the other question is does it work without internet attached and with just the examples.
 
@mick

I picked up a Adfruit pwm servo drive clone from amazon (https://www.amazon.com/dp/B07RMTN4NZ?psc=1&ref=ppx_yo2ov_dt_b_product_details) and gave your sketch in post #2 a try. Like Paul the serial monitor showed "Hi!" but to check UDP I ran a windows app - Packet Sender - and sent a message from the pc to the Teensy and all seems to be working:
Capture.PNG

So looks like I would need at least 5 of those boards to test with. But before that can I ask you to run I2Cscanner (from the examples menu select Wire -> I2Cscanner) in order to check that you have 5 unique I2C address:
Code:
Board 0:  Address = 0x40  Offset = binary 00000 (no jumpers required)
Board 1:  Address = 0x41  Offset = binary 00001 (bridge A0 as in the photo above)
Board 2:  Address = 0x42  Offset = binary 00010 (bridge A1)
Board 3:  Address = 0x43  Offset = binary 00011 (bridge A0 & A1)
Board 4:  Address = 0x44  Offset = binary 00100 (bridge A2)

etc.

Thanks
Mike
 
@PaulStoffregen and @mick

I picked up 4 more of the HiLetgo pwm servo drivers (knock offs of the adaftruit) so now I have a total of 5 of the drivers attached to the T4.1.

IMG-0737.jpg

Running I2CScanner:
Code:
Scanning...
Device found at address 0x40  (PCA9685,Si7021)
Device found at address 0x41  (STMPE610,PCA9685)
Device found at address 0x42  (PCA9685)
Device found at address 0x43  (PCA9685)
Device found at address 0x44  (PCA9685)
Device found at address 0x70  (AdafruitLED)
done

and running the sketch in post #2 again
ATTACH=CONFIG]29300[/ATTACH]

I am getting the blinking LED and am able to receive packets and get the acknowledge packet back.

So not sure what you mean by stop responding?

EDIT: I did just turn debug on in the adafruit library and didn't see where setPWM was failing or stopping?
 

Attachments

  • Capture.PNG
    Capture.PNG
    69.1 KB · Views: 25
Last edited:
I picked up 4 more of the HiLetgo pwm servo drivers (knock offs of the adaftruit) so now I have a total of 5 of the drivers attached to the T4.1.

Wow, nice work on this test setup!

Sounds like this issue isn't reproducible. Going to take it off my list... at least until more specific steps to reproduce the problem are given.
 
Wow, nice work on this test setup!

Sounds like this issue isn't reproducible. Going to take it off my list... at least until more specific steps to reproduce the problem are given.

Thanks. Was waiting on some additional info but not sure where to go from here. Still thinking about hooking up a servo to board #5 or hook up a LA just to if the signals are good. Any other ideas would be apprecated
 
@PaulStoffregen

Ok out of curiosity attached the LA to the I2C lines on the T4 to see if it stopped working while sending packets - short answer looked like on the LA I2C stayed operational

Capture.jpg

With that send with the new toolchain did get warnings from the library:
Code:
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\NativeEthernet\src\NativeEthernetServer.cpp: In member function 'EthernetClient EthernetServer::available()':
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\NativeEthernet\src\NativeEthernetServer.cpp:119:103: warning: enum constant in boolean context [-Wint-in-bool-context]
  119 |                                            if(socket_poll.events_occurred & (FNET_SOCKET_EVENT_OUT || FNET_SOCKET_EVENT_IN)) {
      |                                                                                                       ^~~~~~~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\service\llmnr\fnet_llmnr.c:60:30: warning: 'fnet_llmnr_ip6_multicast_addr' defined but not used [-Wunused-const-variable=]
   60 | static const fnet_ip6_addr_t fnet_llmnr_ip6_multicast_addr = FNET_IP6_ADDR_INIT(0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0x00, 0x03);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:1062:83: warning: argument 2 of type 'unsigned char[36]' with mismatched bound [-Warray-parameter=]
 1062 | MBEDTLSFLASHMEM void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] )
      |                                                                     ~~~~~~~~~~~~~~^~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:483:73: note: previously declared as 'unsigned char *'
  483 | MBEDTLSFLASHMEM static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * );
      |                                                                         ^~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:1090:90: warning: argument 2 of type 'unsigned char[32]' with mismatched bound [-Warray-parameter=]
 1090 | MBEDTLSFLASHMEM void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] )
      |                                                                            ~~~~~~~~~~~~~~^~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:490:79: note: previously declared as 'unsigned char *'
  490 | MBEDTLSFLASHMEM static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * );
      |                                                                               ^~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:1111:90: warning: argument 2 of type 'unsigned char[48]' with mismatched bound [-Warray-parameter=]
 1111 | MBEDTLSFLASHMEM void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] )
      |                                                                            ~~~~~~~~~~~~~~^~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:496:80: note: previously declared as 'unsigned char *'
  496 | MBEDTLSFLASHMEM static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * );
      |                                                                                ^~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c: In function 'ssl_calc_verify_tls_sha384':
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:1120:5: warning: 'mbedtls_sha512_finish_ret' accessing 64 bytes in a region of size 48 [-Wstringop-overflow=]
 1120 |     mbedtls_sha512_finish_ret( &sha512, hash );
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:1120:5: note: referencing argument 2 of type 'unsigned char *'
In file included from C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\mbedtls/ssl_internal.h:43,
                 from C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:48:
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\mbedtls/sha512.h:128:21: note: in a call to function 'mbedtls_sha512_finish_ret'
  128 | MBEDTLSFLASHMEM int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c: In function 'ssl_calc_finished_tls_sha384':
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:5376:5: warning: 'mbedtls_sha512_finish_ret' accessing 64 bytes in a region of size 48 [-Wstringop-overflow=]
 5376 |     mbedtls_sha512_finish_ret( &sha512, padbuf );
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:5376:5: note: referencing argument 2 of type 'unsigned char *'
In file included from C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\mbedtls/ssl_internal.h:43,
                 from C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\ssl_tls.c:48:
C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.0-beta1\libraries\FNET\src\third_party\mbedtls-2.12.0\src\mbedtls/sha512.h:128:21: note: in a call to function 'mbedtls_sha512_finish_ret'
  128 | MBEDTLSFLASHMEM int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~
Memory Usage on Teensy 4.1:
  FLASH: code:224568, data:75184, headers:8952   free for files:7817760
   RAM1: variables:30116, code:89608, padding:8696   free for local variables:395868
   RAM2: variables:12416  free for malloc/new:511872
 
@PaulStoffregen and @mick

Just out of curiosity and as a final test case I attached a servo to 0x40 and 0x41 and ran the test case which is set up just to test the servo on board 0x40. The servo continued to rotate even with me sending UDP packets from the PC to the T4.1.


Code:
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";        // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// 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

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#define PWM_NUM 5
Adafruit_PWMServoDriver pwm[] = { (0x40), {0x41},(0x42), {0x43}, (0x44)  };

// Depending on your servo make, the pulse width min and max may vary, you 
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN  150 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // This is the 'maximum' pulse length count (out of 4096)
#define USMIN  600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX  2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

// our servo # counter
uint8_t servonum = 0;
void setup() {

  pinMode(ledPin, OUTPUT);

  for (uint8_t p = 0; p < PWM_NUM; p++) {
    pwm[p].begin();
    pwm[p].setOscillatorFrequency(27000000);
    pwm[p].setPWMFreq(SERVO_FREQ);  // This is the maximum PWM frequency
  }
  Wire.setClock(400000);

  // start the Ethernet
  Ethernet.begin(mac, ip);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("hi!");

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start UDP
  Udp.begin(localPort);
}

void loop() {

  float b = map(sin(millis() * 0.01), -1, 1, 0, 1);
  int t = b * 4095;

 // Drive each servo one at a time using setPWM()
  Serial.println(servonum);
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm[0].setPWM(servonum, 0, pulselen);
  }

  delay(500);
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm[0].setPWM(servonum, 0, pulselen);
  }

  delay(500);

  // Drive each servo one at a time using writeMicroseconds(), it's not precise due to calculation rounding!
  // The writeMicroseconds() function is used to mimic the Arduino Servo library writeMicroseconds() behavior. 
  for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
    pwm[0].writeMicroseconds(servonum, microsec);
  }

  delay(500);
  for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
    pwm[0].writeMicroseconds(servonum, microsec);
  }

  delay(500);

  servonum++;
  if (servonum > 2) servonum = 0; // Testing the first 8 servo channels

  
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  //delay(10);

  unsigned long currentMillis = millis();

  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);
  }
}
 
Back
Top