In module hierarchy, on connecting inout port with sc_signal it shows error, So is there any other type of signal I need to connect with inout (bidirectional port) ?
Error: (E115) sc_signal cannot have more than one driver:
signal Dha.signal_0' (sc_signal)
first driverDha.Memory.port_4' (sc_inout)
second driver `Dha.Alloc.port_3' (sc_inout)
You need to instantiate the sc_signal with a writer policy of SC_MANY_WRITERS to drive a signal from multiple ports/processes.
#include <systemc.h>
SC_MODULE(Foo) {
sc_inout<bool> port;
SC_CTOR(Foo)
: port("port")
{}
// ...
};
SC_MODULE(Bar) {
sc_inout<bool> port;
SC_CTOR(Bar)
: port("port")
{}
// ...
};
int sc_main(int, char*[])
{
sc_signal<bool, SC_MANY_WRITERS> signal; // <-- policy here
Foo foo("foo");
Bar bar("bar");
foo.port(signal);
bar.port(signal);
sc_start();
return 0;
}
You need sc_signal_rv. Check example here http://www.asic-world.com/systemc/ports_signals4.html#Example_:_Resolved_Vector_Signals
Related
I'm trying to make interrupt work for a device in qemu. The machnie name is ab21q, a modified version of arm64 virt machine, and the device name is ab21q_axpu.
Here are some relevant codes. I referenced pl011.c. (I switched temporarily back to qemu-5.1.0 for this test.)
==== hw/arm/ab21q.c
machab21q_init(MachineState *machine)
{
.... skip ....
create_ab21q_axpu_device(vms, sysmem); // ab21q-axpu test
....
}
static void create_ab21q_axpu_device(const Ab21qMachineState *vms, MemoryRegion *mem)
{
char *nodename;
hwaddr base = vms->memmap[AB21Q_AXPU].base;
hwaddr size = vms->memmap[AB21Q_AXPU].size;
int irq = vms->irqmap[AB21Q_AXPU];
const char compat[] = "ab21q-axpu";
DeviceState *dev = qdev_new(TYPE_AB21Q_AXPU);
SysBusDevice *s = SYS_BUS_DEVICE(dev);
//sysbus_create_simple("ab21q-axpu", base, qdev_get_gpio_in(vms->gic, irq));
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
memory_region_add_subregion(mem, base,
sysbus_mmio_get_region(s, 0));
sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
nodename = g_strdup_printf("/ab21q_axpu#%" PRIx64, base);
qemu_fdt_add_subnode(vms->fdt, nodename);
qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
qemu_fdt_setprop_cell(vms->fdt, nodename, "interrupt-parent", vms->gic_phandle);
g_free(nodename);
}
==== hw/misc/ab21q_axpu.c
static void ab21q_axpu_init(Object *obj)
{
Ab21qAxpuState *s = AB21Q_AXPU(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
int i;
memory_region_init_io(&s->iomem, OBJECT(s), &ab21q_axpu_ops, s,
TYPE_AB21Q_AXPU, 0x200000*64);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
s->init = 0;
s->int_flag = 0;
s->status = 0;
s->id = CHIP_ID;
}
static void ab21q_axpu_realize(DeviceState *d, Error **errp)
{
Ab21qAxpuState *s = AB21Q_AXPU(d);
SysBusDevice *sbd = SYS_BUS_DEVICE(d);
if (qemu_irq_is_connected(s->irq)) {printf("axpu irq connected!\n");}
else { printf("axpu irq not connected!\n");}
}
static void ab21q_axpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = ab21q_axpu_realize;
}
static void ab21q_axpu_set_irq(Ab21qAxpuState *s, int irq)
{
s->status = irq;
qemu_set_irq(s->irq, 1);
}
static void ab21q_axpu_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
Ab21qAxpuState *s = (Ab21qAxpuState *)opaque;
.... skip ...
switch (offset) {
case TRIGGER_RUN:
....
if (((uint64_t *)(s->ioctl_arg + *host_virt_offset_p))[0] == 0x1604) {
s->int_flag = 1;
ab21q_axpu_set_irq(s, INT_AXPU_RUN_FINISHED);
}
The machine and the device works. (actually the device is a shared library that qemu links to) except the interrupt doesn't work even though qemu does set_irq. I checked with qemu_irq_is_connected in realize function. The pl011 case says pl011 irq connected!, but in my device I see axpu irq not connected!. So it's not related to device driver but qemu model itself.
Could anyone find what is missing in the above code? Should I add something to acpi table(in ab21q-build-acpi.c)?
I tried adding in hw/arm/ab21q-build-acpi.c these lines. In function build_dsdt,
acpi_dsdt_add_axpu(scope, &memmap[AB21Q_AXPU],
(irqmap[AB21Q_AXPU] + ARM_SPI_BASE));
The acpi_dsdt_add_axpu function being
static void acpi_dsdt_add_axpu(Aml *scope, const MemMapEntry *uart_memmap,
uint32_t irq)
{
Aml *dev = aml_device("AXPU");
aml_append(dev, aml_name_decl("_HID", aml_string("AXPU0011")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
Aml *crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(uart_memmap->base,
uart_memmap->size, AML_READ_WRITE));
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, &irq, 1));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
Inside the virtual machine (ubuntu 20.04), I did acpidump and converted it to .dsl files. The dsdt.dsl contains this entry.
Device (AXPU)
{
Name (_HID, "AXPU0011") // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
Memory32Fixed (ReadWrite,
0x09100000, // Address Base
0x00080000, // Address Length
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
{
0x000000D0,
}
})
}
I'm not sure what I should fix in acpi table.
Any comment or advice will be deeply appreciated.
Thank you!
Chan Kim
So I added some prints. This is the result.
create_uart called!
pl011_init called!
pl011_realize called!
pl011 irq not connected!
now calling sysbus_connect_irq for pl011..
now passed sysbus_connect_irq for pl011..
pl011 irq connected!
create_ab21q_axpu_device called!
ab21q_axpu_init called!
ab21q_axpu_realize called!
axpu irq not connected!
now calling sysbus_connect_irq for ab21q_axpu..
now passed sysbus_connect_irq for ab21q_axpu..
ab21q_axpu irq connected!
So irq-connection-wise speaking, pl011 and ab21q_axpu is the same!
For pl011, the irq was not connected either before the sysbus_connect_irq,
but in the code above, I used qemu_irq_is_connected(s->irq)) by mistake and it gave me true (a false true). I fixed it to qemu_irq_is_connected(s->irq[0])) because it had 6 irq outputs and it returned false before the sysbus_connect_irq. After the sysbus_connect_irq, both ab21q_axpu and pl011's irq shown to have been connected.
And of course I used qemu_irq_is_connected(AB21Q_AXPU(dev)->irq) or
qemu_irq_is_connected(PL011(dev)->irq[0]) to check the irq connection inside the xxx_create functions.
ADD : I later found the request_irq functino returned -EINVAL. so interrupt was not registerred correctly in the driver.
I'm trying to send data to and from my computer and an STM32H745 over Ethernet using LwIP and UDP. I have successfully configured the card and right now I can send data from the card to a Python script running on the computer. However, I don't understand how udp_recv works <udp,lwip> or how to receive data with UDP on LwIP in general, and I can't find examples that do just that. Where is the data being received? Should I even use udp_recv?
In the main loop I run MX_LWIP_Process, which runs ethernetif_input which somehow handles the received data, but I don't understand where it puts it.
Below is the main code, just for reference.
const char* message = "a";
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange
ip_addr_t PC_IPADDR;
IP_ADDR4(&PC_IPADDR, 192, 168, 1, 200);
u16_t port = 8000;
struct udp_pcb* my_udp = udp_new();
struct pbuf* udp_buffer = NULL;
/* Infinite loop */
for (;; )
{
MX_LWIP_Process();
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange
HAL_Delay(1000);
udp_buffer = pbuf_alloc(PBUF_TRANSPORT, strlen(message), PBUF_RAM);
if (udp_buffer != NULL)
{
memcpy(udp_buffer->payload, message, strlen(message));
udp_sendto(my_udp, udp_buffer,&PC_IPADDR, port);
pbuf_free(udp_buffer);
}
//udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
}
udp_recv() does not actually receive UDP datagrams (despite its name). It registers a callback function that will then be called by MX_LWIP_Process() when a datagram has been buffered. It would better be called udp_set_recv_callback(), but it is what it is.
To that end you should call it once before your executive loop:
udp_bind( my_udp, IP_ADDR_ANY, port ) ;
udp_recv( my_udp, udp_receive_callback, NULL ) ;
/* Infinite loop */
for (;; )
{
// Run the CubeMX LwIP stack
MX_LWIP_Process() ;
...
}
Where udp_receive_callback is a function that will be invoked on receipt of a datagram:
void udp_receive_callback( void* arg, // User argument - udp_recv `arg` parameter
struct udp_pcb* upcb, // Receiving Protocol Control Block
struct pbuf* p, // Pointer to Datagram
const ip_addr_t* addr, // Address of sender
u16_t port ) // Sender port
{
// Process datagram here (non-blocking code)
...
// Must free receive pbuf before return
pbuf_free(p);
}
Examples include:
https://gist.github.com/iwanbk/1399729
https://github.com/STMicroelectronics/STM32CubeF2/blob/master/Projects/STM322xG_EVAL/Applications/LwIP/LwIP_UDP_Echo_Client/Src/udp_echoclient.c
Documentation can be found at https://www.nongnu.org/lwip/2_0_x/group__udp__raw.html
I'm using a Nucleo L496ZG, X-NUCLEO-IKS01A2 and the Quectel BG96 module to send sensor data (temperature, humidity etc..) to Azure IoT Central over HTTP.
I've been using the example implementation provided by Avnet here, which works fine but it's not power optimized and with a 6700mAh battery pack it only lasts around 30 hours sending telemetry ever ~10 seconds. Goal is for it to last around a week. I'm open to increasing the time between messages but I also want to save power in between sending.
I've gone over the Quectel BG96 manuals and I've tried two things:
1) powering off the device by driving the PWRKEY and turning it back on when I need to send a message
I've gotten this to work, kinda… until I get a hardfault exception which happens seemingly randomly anywhere from within ~5 minutes of running to 2 hours (messages successfully sending prior to the exception). Output of crash log parser is the same every time:
Crash location = strncmp [0x08038DF8] (based on PC value)
Caller location = _findenv_r [0x0804119D] (based on LR value)
Stack Pointer at the time of crash = [20008128]
Target and Fault Info:
Processor Arch: ARM-V7M or above
Processor Variant: C24
Forced exception, a fault with configurable priority has been escalated to HardFault
A precise data access error has occurred. Faulting address: 03060B30
The caller location traces back to my .map file and I don't know what to make of it.
My code:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//#define USE_MQTT
#include <stdlib.h>
#include "mbed.h"
#include "iothubtransporthttp.h"
#include "iothub_client_core_common.h"
#include "iothub_client_ll.h"
#include "azure_c_shared_utility/platform.h"
#include "azure_c_shared_utility/agenttime.h"
#include "jsondecoder.h"
#include "bg96gps.hpp"
#include "azure_message_helper.h"
#define IOT_AGENT_OK CODEFIRST_OK
#include "azure_certs.h"
/* initialize the expansion board && sensors */
#include "XNucleoIKS01A2.h"
static HTS221Sensor *hum_temp;
static LSM6DSLSensor *acc_gyro;
static LPS22HBSensor *pressure;
static const char* connectionString = "xxx";
// to report F uncomment this #define CTOF(x) (((double)(x)*9/5)+32)
#define CTOF(x) (x)
Thread azure_client_thread(osPriorityNormal, 10*1024, NULL, "azure_client_thread");
static void azure_task(void);
EventFlags deleteOK;
size_t g_message_count_send_confirmations;
/* create the GPS elements for example program */
BG96Interface* bg96Interface;
//static int tilt_event;
// void mems_int1(void)
// {
// tilt_event++;
// }
void mems_init(void)
{
//acc_gyro->attach_int1_irq(&mems_int1); // Attach callback to LSM6DSL INT1
hum_temp->enable(); // Enable HTS221 enviromental sensor
pressure->enable(); // Enable barametric pressure sensor
acc_gyro->enable_x(); // Enable LSM6DSL accelerometer
//acc_gyro->enable_tilt_detection(); // Enable Tilt Detection
}
void powerUp(void) {
if (platform_init() != 0) {
printf("Error initializing the platform\r\n");
return;
}
bg96Interface = (BG96Interface*) easy_get_netif(true);
}
void BG96_Modem_PowerOFF(void)
{
DigitalOut BG96_RESET(D7);
DigitalOut BG96_PWRKEY(D10);
DigitalOut BG97_WAKE(D11);
BG96_RESET = 0;
BG96_PWRKEY = 0;
BG97_WAKE = 0;
wait_ms(300);
}
void powerDown(){
platform_deinit();
BG96_Modem_PowerOFF();
}
//
// The main routine simply prints a banner, initializes the system
// starts the worker threads and waits for a termination (join)
int main(void)
{
//printStartMessage();
XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(I2C_SDA, I2C_SCL, D4, D5);
hum_temp = mems_expansion_board->ht_sensor;
acc_gyro = mems_expansion_board->acc_gyro;
pressure = mems_expansion_board->pt_sensor;
azure_client_thread.start(azure_task);
azure_client_thread.join();
platform_deinit();
printf(" - - - - - - - ALL DONE - - - - - - - \n");
return 0;
}
static void send_confirm_callback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
//userContextCallback;
// When a message is sent this callback will get envoked
g_message_count_send_confirmations++;
deleteOK.set(0x1);
}
void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, char* buffer, size_t size)
{
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)buffer, size);
if (messageHandle == NULL) {
printf("unable to create a new IoTHubMessage\r\n");
return;
}
if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, send_confirm_callback, NULL) != IOTHUB_CLIENT_OK)
printf("FAILED to send! [RSSI=%d]\n", platform_RSSI());
else
printf("OK. [RSSI=%d]\n",platform_RSSI());
IoTHubMessage_Destroy(messageHandle);
}
void azure_task(void)
{
//bool tilt_detection_enabled=true;
float gtemp, ghumid, gpress;
int k;
int msg_sent=1;
while (true) {
powerUp();
mems_init();
/* Setup IoTHub client configuration */
IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, HTTP_Protocol);
if (iotHubClientHandle == NULL) {
printf("Failed on IoTHubClient_Create\r\n");
return;
}
// add the certificate information
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
printf("failure to set option \"TrustedCerts\"\r\n");
#if MBED_CONF_APP_TELUSKIT == 1
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "product_info", "TELUSIOTKIT") != IOTHUB_CLIENT_OK)
printf("failure to set option \"product_info\"\r\n");
#endif
// polls will happen effectively at ~10 seconds. The default value of minimumPollingTime is 25 minutes.
// For more information, see:
// https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
unsigned int minimumPollingTime = 9;
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
printf("failure to set option \"MinimumPollingTime\"\r\n");
IoTDevice* iotDev = (IoTDevice*)malloc(sizeof(IoTDevice));
if (iotDev == NULL) {
return;
}
setUpIotStruct(iotDev);
char* msg;
size_t msgSize;
hum_temp->get_temperature(>emp); // get Temp
hum_temp->get_humidity(&ghumid); // get Humidity
pressure->get_pressure(&gpress); // get pressure
iotDev->Temperature = CTOF(gtemp);
iotDev->Humidity = (int)ghumid;
iotDev->Pressure = (int)gpress;
printf("(%04d)",msg_sent++);
msg = makeMessage(iotDev);
msgSize = strlen(msg);
sendMessage(iotHubClientHandle, msg, msgSize);
free(msg);
iotDev->Tilt &= 0x2;
/* schedule IoTHubClient to send events/receive commands */
IOTHUB_CLIENT_STATUS status;
while ((IoTHubClient_LL_GetSendStatus(iotHubClientHandle, &status) == IOTHUB_CLIENT_OK) && (status == IOTHUB_CLIENT_SEND_STATUS_BUSY))
{
IoTHubClient_LL_DoWork(iotHubClientHandle);
ThisThread::sleep_for(100);
}
deleteOK.wait_all(0x1);
free(iotDev);
IoTHubClient_LL_Destroy(iotHubClientHandle);
powerDown();
ThisThread::sleep_for(300000);
}
return;
}
I know PSM is probably the way to go since powering on/off the device draws a lot of power but it would be useful if someone had an idea of what is happening here.
2) putting the device to PSM between sending messages
The BG96 library in the example code I'm using doesn't have a method to turn on PSM so I tried to implement my own. When I tried to run it, it basically runs into an exception right away so I know it's wrong (I'm very new to embedded development and have no prior experience with AT commands).
/** ----------------------------------------------------------
* this is a method provided by current library
* #brief Tx a string to the BG96 and wait for an OK response
* #param none
* #retval true if OK received, false otherwise
*/
bool BG96::tx2bg96(char* cmd) {
bool ok=false;
_bg96_mutex.lock();
ok=_parser.send(cmd) && _parser.recv("OK");
_bg96_mutex.unlock();
return ok;
}
/**
* method I created in an attempt to use PSM
*/
bool BG96::psm(void) {
return tx2bg96((char*)"AT+CPSMS=1,,,”00000100”,”00000001”");
}
Can someone tell me what I'm doing wrong and provide any guidance on how I can achieve my goal of having my device run on battery for longer?
Thank you!!
I got Power Saving Mode working by using Mbed's ATCmdParser and the AT+QPSMS commands as per Quectel's docs. The modem doesn't always go into power saving mode right away so that should be noted. I also found that I have to restart the modem afterwards or else I get weird behaviour. My code looks something like this:
bool BG96::psm(char* T3412, char* T3324) {
_bg96_mutex.lock();
if(_parser.send("AT+QPSMS=1,,,\"%s\",\"%s\"", T3412, T3324) && _parser.recv("OK")) {
_bg96_mutex.unlock();
}else {
_bg96_mutex.unlock();
return false;
}
return BG96Ready(); }//restarts modem
To send a message to Azure, the modem will need to be manually woken up by driving the PWRKEY to start bi-directional communication, and a new client handle needs to be created and torn down every time since Azure connection uses keepAlive and the modem will be unreachable when it's in PSM.
I have a Raspberry Pi working as a WiFi hotspot and an Arduino Uno trying to get data from it using an ESP8266 module.
This is my receiver code for Arduino:
#include <SoftwareSerial.h>
#include <SerialESP8266wifi.h>
#define sw_serial_rx_pin 4 // Connect this pin to TX on the esp8266
#define sw_serial_tx_pin 6 // Connect this pin to RX on the esp8266
#define esp8266_reset_pin 5 // Connect this pin to CH_PD on the esp8266, not reset. (let reset be unconnected)
SoftwareSerial swSerial(sw_serial_rx_pin, sw_serial_tx_pin);
// the last parameter sets the local echo option for the ESP8266 module..
SerialESP8266wifi wifi(swSerial, swSerial, esp8266_reset_pin, Serial);//adding Serial enabled local echo and wifi debug
String inputString;
boolean stringComplete = false;
unsigned long nextPing = 0;
void setup() {
inputString.reserve(20);
swSerial.begin(9600);
Serial.begin(9600);
while (!Serial)
;
Serial.println("Starting wifi");
wifi.setTransportToTCP();// this is also default
// wifi.setTransportToUDP();//Will use UDP when connecting to server, default is TCP
wifi.endSendWithNewline(true); // Will end all transmissions with a newline and carriage return ie println.. default is true
wifi.begin();
wifi.connectToAP("RPi", "raspberry");
wifi.connectToServer("192.168.50.1", "1234");
wifi.send(SERVER, "ESP8266 test app started");
}
void loop() {
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
if (stringComplete) {
inputString.toCharArray(buf, sizeof buf);
wifi.send(SERVER, buf);
inputString = "";
stringComplete = false;
}
//Send a ping once in a while..
if (millis() > nextPing) {
wifi.send(SERVER, "Ping ping..");
nextPing = millis() + 10000;
}
//Listen for incoming messages and echo back, will wait until a message is received, or max 6000ms..
WifiMessage in = wifi.listenForIncomingMessage(6000);
if (in.hasData) {
if (in.channel == SERVER)
Serial.println("Message from the server:");
else
Serial.println("Message a local client:");
Serial.println(in.message);
//Echo back;
wifi.send(in.channel, "Echo:", false);
wifi.send(in.channel, in.message);
nextPing = millis() + 10000;
}
//If you want do disconnect from the server use:
// wifi.disconnectFromServer();
}
//Listen for serial input from the console
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
When I execute, the serial monitor shows:
OK ARFa C⸮C⸮j⸮H⸮AT+AWJAP="RPi",#raspberry" WIFI DISCONNECT WIFI
CONNECVED WIFI GOT IP
OK AT+CIFSR
+CIFSR:STAIP,"192.168.50.13"
+CIFQR:STAMAC,"2c:3a:eAT+CIPSTART=4,"TCP","192.0n8.50.1",121l
Link type ERROR
Raspberry Pi's ISC DHCP server:
wlan0: STA 2c:3a:e8:4e:bf:70 RADIUS: starting accounting session
5A3B2C85-000000E9 wlan0: STA 2c:3a:e8:4e:bf:70 WPA: pairwise key
handshake completed (RSN)
I also referred to this SO thread with no luck.
Some assumptions because you have not given the info:
Arduino IDE >=1.85
ESP8266 Community package >=2.41
ESP Module ESP8266-12E with latest AT firmware
if that is the case and these fragments (enclosed by X X) are no typos
+CIFQR:STAMAC,"2c:3a:eXAT+CIPSTART=4,"TCP","192.0XnX8.50.1",121l
this leaves the following points to check
hardware connectors - serial connectors between arduino and esp module
stable power source 3.3V for the ESP module
Sure this is ok - but just in case and as reference for other readers
serial speed - try to increase from 9600 to 57600 or even to 115200 baud
These pieces of code should be in the setup() and not in the loop()
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
Code processing
nextPing = millis() + 10000;
at the end of
if (in.hasData) {
might lead to interuptions in the communication
Reason due to the processing of code this might trigger at an unwanted point
Below you can see my code that implements a pretty basic UDP sender in C++ with Winsock. The thing is that no matter how many times I run the code, the socket (the listenSocket) gets bound to a different UDP port. Is there any specific reason for this? Am I doing some mistake in my code?
thanks
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKADDR_IN myAddress;
SOCKADDR_IN targetAddress;
int myPort = 60888;
const char *myIP = "192.168.0.1";
int remotePort = 2048;
const char *remoteIP = "192.168.0.2";
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET SendSocket = INVALID_SOCKET;
SOCKET acceptSocket;
char cBuffer[1024] = "Test Buffer";
int nBytesSent = 0;
int nBufSize = strlen(cBuffer);
int iResult;
// Initialize Winsock
if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
{
cerr<<"Socket Initialization: Error with WSAStartup\n";
system("pause");
WSACleanup();
exit(10);
}
ListenSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET or SendSocket == INVALID_SOCKET)
{
cerr<<"Socket Initialization: Error creating socket"<<endl;
system("pause");
WSACleanup();
exit(11);
}
//bind
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr(myIP);
myAddress.sin_port = htons(myPort);
targetAddress.sin_family = AF_INET;
targetAddress.sin_addr.s_addr = inet_addr(remoteIP);
targetAddress.sin_port = htons(remotePort);
if(bind(ListenSocket, (SOCKADDR*) &myAddress, sizeof(myAddress)) == SOCKET_ERROR)
{
cerr<<"ServerSocket: Failed to connect\n";
system("pause");
WSACleanup();
exit(14);
}
else
printf("Server: bind() is OK.\n");
nBytesSent = sendto(SendSocket, cBuffer, nBufSize, 0,
(SOCKADDR *) &targetAddress,
sizeof(SOCKADDR_IN));
printf("Everything is ok\n");
system("PAUSE");
closesocket(ListenSocket);
closesocket(SendSocket);
return EXIT_SUCCESS;
}
EDIT: Maybe I was not so clear. What I do with this code is to send some data to a remote PC. But what is required is that the UDP segments should appear to be originated from a specific port. How can this be done? Is it wrong what I'm doing here? Now that I'm thinking of it, I guess it is wrong indeed. The SendSocket and ListenSocket don't have any connection, correct? So, how can I make it that the UDP segments appear to originate from a specific UDP port? Thanks!
You are not calling bind() on SendSocket before sending data with it, so WinSock is free to bind that socket to whatever random local IP/Port it needs to. If you have to send data with a specific source IP/Port every time, you have to bind() to that IP/Port first. If that local IP/Port is the same pair you are binding ListenSocket to, then you don't need to use two separate sockets to begin with. You can send data with the same socket that is listening for incoming data.